Skip to content
Snippets Groups Projects
Commit 33a89dc4 authored by juanf's avatar juanf
Browse files

SSDM-13154 : Working adapter tests

parent 17c7a3c4
No related branches found
No related tags found
1 merge request!40SSDM-13578 : 2PT : Database and V3 Implementation - include the new AFS "free"...
......@@ -5,6 +5,7 @@ import ch.ethz.sis.afsserver.http.*;
import ch.ethz.sis.afsserver.server.*;
import ch.ethz.sis.afsserver.server.performance.Event;
import ch.ethz.sis.afsserver.server.performance.PerformanceAuditor;
import ch.ethz.sis.shared.io.IOUtils;
import ch.ethz.sis.shared.json.JSONObjectMapper;
import ch.ethz.sis.shared.log.LogManager;
import ch.ethz.sis.shared.log.Logger;
......@@ -43,7 +44,7 @@ public class ApiServerAdapter<CONNECTION, API> implements HttpServerHandler {
String transactionManagerKey = null;
Map<String, Object> methodParameters = new HashMap<>();
for (Map.Entry<String, List<String>> entry:uriParameters.entrySet()) {
Object value = null;
String value = null;
if (entry.getValue() != null) {
if (entry.getValue().size() == 1) {
value = entry.getValue().get(0);
......@@ -54,16 +55,31 @@ public class ApiServerAdapter<CONNECTION, API> implements HttpServerHandler {
switch (entry.getKey()) {
case "method":
method = (String) value;
method = value;
break;
case "sessionToken":
sessionToken = (String) value;
sessionToken = value;
break;
case "interactiveSessionKey":
interactiveSessionKey = (String) value;
interactiveSessionKey = value;
break;
case "transactionManagerKey":
transactionManagerKey = (String) value;
transactionManagerKey = value;
break;
case "transactionId":
methodParameters.put(entry.getKey(), UUID.fromString(value));
break;
case "recursively":
methodParameters.put(entry.getKey(), Boolean.valueOf(value));
break;
case "offset":
methodParameters.put(entry.getKey(), Long.valueOf(value));
break;
case "limit":
methodParameters.put(entry.getKey(), Integer.valueOf(value));
break;
case "md5Hash":
methodParameters.put(entry.getKey(), IOUtils.decodeBase64(value));
break;
default:
methodParameters.put(entry.getKey(), value);
......@@ -71,6 +87,10 @@ public class ApiServerAdapter<CONNECTION, API> implements HttpServerHandler {
}
}
if (method.equals("write")) {
methodParameters.put("data", requestBody);
}
ApiRequest apiRequest = new ApiRequest("1", method, methodParameters, sessionToken, interactiveSessionKey, transactionManagerKey);
Response response = server.processOperation(apiRequest, apiResponseBuilder, performanceAuditor);
HttpResponse httpResponse = getHTTPResponse(response);
......
package ch.ethz.sis.afsserver.impl;
import ch.ethz.sis.afsserver.core.AbstractPublicAPIWrapper;
import ch.ethz.sis.afsserver.http.HttpResponse;
import ch.ethz.sis.afsserver.server.impl.ApiRequest;
import ch.ethz.sis.afsserver.server.impl.ApiResponse;
import ch.ethz.sis.afsserver.server.impl.ApiServerAdapter;
import ch.ethz.sis.afsserver.server.performance.PerformanceAuditor;
import ch.ethz.sis.shared.io.IOUtils;
import ch.ethz.sis.shared.json.JSONObjectMapper;
import ch.ethz.sis.shared.log.LogManager;
import ch.ethz.sis.shared.log.Logger;
import io.netty.handler.codec.http.HttpMethod;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static ch.ethz.sis.afsserver.http.HttpResponse.CONTENT_TYPE_BINARY_DATA;
import static ch.ethz.sis.afsserver.http.HttpResponse.CONTENT_TYPE_JSON;
public class APIServerAdapterWrapper extends AbstractPublicAPIWrapper {
private static final Logger logger = LogManager.getLogger(APIServerAdapterWrapper.class);
private ApiServerAdapter apiServerAdapter;
private JSONObjectMapper jsonObjectMapper;
public APIServerAdapterWrapper(ApiServerAdapter apiServerAdapter, JSONObjectMapper jsonObjectMapper) {
this.apiServerAdapter = apiServerAdapter;
this.jsonObjectMapper = jsonObjectMapper;
}
public Map<String, List<String>> getURIParameters(Map<String, Object> args) {
Map<String, List<String>> result = new HashMap<>(args.size());
for (Map.Entry<String, Object> entry:args.entrySet()) {
if (entry.getKey().equals("data") && entry.getValue() instanceof byte[]) {
continue; // Skip
} else if(entry.getValue() instanceof byte[]) {
result.put(entry.getKey(), List.of(IOUtils.encodeBase64((byte[]) entry.getValue())));
} else {
result.put(entry.getKey(), List.of(String.valueOf(entry.getValue())));
}
}
return result;
}
public <E> E process(String method, Map<String, Object> args) {
try {
HttpMethod httpMethod = null;
switch (method){
case "delete":
httpMethod = HttpMethod.DELETE;
break;
case "write":
httpMethod = HttpMethod.PUT;
break;
case "list":
case "read":
case "isSessionValid":
httpMethod = HttpMethod.GET;
break;
default:
httpMethod = HttpMethod.POST;
}
Map<String, List<String>> uriParameters = getURIParameters(args);
uriParameters.put("method", List.of(method));
uriParameters.put("sessionToken", List.of(UUID.randomUUID().toString()));
byte[] requestBody = null;
if (method.equals("write")) {
requestBody = (byte[]) args.get("data");
}
HttpResponse response = apiServerAdapter.process(httpMethod, uriParameters, requestBody);
switch (response.getContentType()) {
case CONTENT_TYPE_BINARY_DATA:
return (E) response.getBody();
case CONTENT_TYPE_JSON:
ApiResponse apiResponse = jsonObjectMapper.readValue(new ByteArrayInputStream(response.getBody()), ApiResponse.class);
return (E) apiResponse.getResult();
}
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
throw new RuntimeException("This line should be unreachable");
}
}
......@@ -13,15 +13,15 @@ import ch.ethz.sis.shared.log.Logger;
import java.util.Map;
import java.util.UUID;
public class PublicAPIAdapterWrapper extends AbstractPublicAPIWrapper {
public class APIServerWrapper extends AbstractPublicAPIWrapper {
private static final Logger logger = LogManager.getLogger(PublicAPIAdapterWrapper.class);
private static final Logger logger = LogManager.getLogger(APIServerWrapper.class);
private APIServer apiServer;
private final ApiResponseBuilder apiResponseBuilder;
public PublicAPIAdapterWrapper(APIServer apiServerAdapter) {
this.apiServer = apiServerAdapter;
public APIServerWrapper(APIServer apiServer) {
this.apiServer = apiServer;
this.apiResponseBuilder = new ApiResponseBuilder();
}
......
package ch.ethz.sis.afsserver.impl;
import ch.ethz.sis.afsserver.ServerClientEnvironmentFS;
import ch.ethz.sis.afsserver.api.PublicAPI;
import ch.ethz.sis.afsserver.server.APIServer;
import ch.ethz.sis.afsserver.server.impl.ApiServerAdapter;
import ch.ethz.sis.afsserver.startup.AtomicFileSystemServerParameter;
import ch.ethz.sis.shared.json.JSONObjectMapper;
import ch.ethz.sis.shared.startup.Configuration;
public class ApiServerAdapterTest extends ApiServerTest {
@Override
public PublicAPI getPublicAPI() throws Exception {
APIServer apiServer = getAPIServer();
Configuration configuration = ServerClientEnvironmentFS.getInstance().getDefaultServerConfiguration();
JSONObjectMapper jsonObjectMapper = configuration.getSharableInstance(AtomicFileSystemServerParameter.jsonObjectMapperClass);
ApiServerAdapter apiServerAdapter = new ApiServerAdapter(apiServer, jsonObjectMapper);
return new APIServerAdapterWrapper(apiServerAdapter, jsonObjectMapper);
}
}
......@@ -15,8 +15,7 @@ import ch.ethz.sis.shared.startup.Configuration;
public class ApiServerTest extends PublicApiTest {
@Override
public PublicAPI getPublicAPI() throws Exception {
protected APIServer getAPIServer() throws Exception {
Configuration configuration = ServerClientEnvironmentFS.getInstance().getDefaultServerConfiguration();
ConnectionFactory connectionFactory = new ConnectionFactory();
......@@ -35,6 +34,11 @@ public class ApiServerTest extends PublicApiTest {
observer.init(configuration);
APIServer apiServer = new APIServer(connectionsPool, workersPool, PublicAPI.class, interactiveSessionKey, transactionManagerKey, apiServerWorkerTimeout, observer);
observer.init(apiServer, configuration);
return new PublicAPIAdapterWrapper(apiServer);
return apiServer;
}
@Override
public PublicAPI getPublicAPI() throws Exception {
return new APIServerWrapper(getAPIServer());
}
}
......@@ -19,7 +19,8 @@ dependencies {
'log4j:log4j-core:2.10.0',
'fasterxml:jackson-annotations:2.9.10',
'fasterxml:jackson-core:2.9.10',
'fasterxml:jackson-databind:2.9.10.8';
'fasterxml:jackson-databind:2.9.10.8',
'fasterxml:jackson-datatype-jsr310:2.9.10';
testImplementation 'junit:junit:4.10'
testRuntimeOnly 'hamcrest:hamcrest-core:1.3'
}
......
......@@ -47,10 +47,7 @@ import java.nio.file.attribute.UserPrincipal;
import java.security.MessageDigest;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
public class IOUtils {
......@@ -617,6 +614,14 @@ public class IOUtils {
}
}
public static String encodeBase64(byte[] input) {
return Base64.getEncoder().encodeToString(input);
}
public static byte[] decodeBase64(String input) {
return Base64.getDecoder().decode(input);
}
public static boolean exists(String source) {
Path sourcePath = getPathObject(source);
return Files.exists(sourcePath);
......
package ch.ethz.sis.shared.json.jackson;
import java.io.InputStream;
import java.nio.charset.Charset;
public interface JSONObjectMapper {
Charset getCharset();
void setCharset(Charset charset);
<T> T readValue(InputStream src, Class<T> valueType) throws Exception;
byte[] writeValue(Object value) throws Exception;
}
......@@ -20,6 +20,7 @@ import ch.ethz.sis.shared.json.JSONObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.InputStream;
......@@ -49,6 +50,7 @@ public class JacksonObjectMapper implements JSONObjectMapper
public JacksonObjectMapper()
{
objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule()); // new module, NOT JSR310Module
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.enableDefaultTyping();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment