Skip to content

Commit

Permalink
[grid]: Propagate errors correctly, but only as w3c encoded/decoded
Browse files Browse the repository at this point in the history
This means that the Grid is now demoable, but there are
still a number of areas that need improvement. Notably,
we should be able to encode errors for local ends that
are only speaking the JSON Wire Protocol, rather than
the w3c dialect.
  • Loading branch information
shs96c committed Feb 18, 2019
1 parent a0214fd commit fe4451e
Show file tree
Hide file tree
Showing 13 changed files with 334 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,14 @@ public BiFunction<JsonInput, PropertySetting, Object> apply(Type type) {
fromJson.setAccessible(true);

return (jsonInput, setting) -> {
Object obj = jsonInput.read(fromJson.getGenericParameterTypes()[0]);
Type argType = fromJson.getGenericParameterTypes()[0];
Object obj;
if (JsonInput.class.equals(argType)) {
obj = jsonInput;
} else {
obj = jsonInput.read(argType);
}

if (obj == null) {
throw new JsonException("Unable to read value to convert for " + type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ private Optional<Result> createSession(HttpClient client, InputStream newSession
blob);

return Stream.of(
new JsonWireProtocolResponse().getResponseFunction(),
new W3CHandshakeResponse().getResponseFunction())
new W3CHandshakeResponse().getResponseFunction(),
new JsonWireProtocolResponse().getResponseFunction())
.map(func -> func.apply(initialResponse))
.filter(Objects::nonNull)
.findFirst();
Expand Down
35 changes: 35 additions & 0 deletions java/client/test/org/openqa/selenium/json/JsonInputTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import static org.openqa.selenium.json.JsonType.STRING;
import static org.openqa.selenium.json.PropertySetting.BY_NAME;

import com.google.common.collect.ImmutableMap;

import org.junit.Test;

import java.io.StringReader;
Expand Down Expand Up @@ -204,8 +206,41 @@ public void shouldDecodeUnicodeEscapesProperly() {
}
}

@Test
public void shouldCallFromJsonWithJsonInputParameter() {
String raw = "{\"message\": \"Cheese!\"}";

try (JsonInput in = new JsonInput(new StringReader(raw), new JsonTypeCoercer(), BY_NAME)) {
HasFromJsonWithJsonInputParameter obj = in.read(HasFromJsonWithJsonInputParameter.class);

assertThat(obj.getMessage()).isEqualTo("Cheese!");
}
}

private JsonInput newInput(String raw) {
StringReader reader = new StringReader(raw);
return new JsonInput(reader, new JsonTypeCoercer(), BY_NAME);
}

public static class HasFromJsonWithJsonInputParameter {

private final String message;

public HasFromJsonWithJsonInputParameter(String message) {
this.message = message;
}

public String getMessage() {
return message;
}

private static HasFromJsonWithJsonInputParameter fromJson(JsonInput input) {
input.beginObject();
input.nextName();
String message = input.nextString();
input.endObject();

return new HasFromJsonWithJsonInputParameter(message);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.openqa.selenium.grid.data;

import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
Expand All @@ -35,7 +37,8 @@

public class DistributorStatus {

private static final Type SUMMARIES_TYPES = new TypeToken<Set<NodeSummary>>(){}.getType();
private static final Type SUMMARIES_TYPES = new TypeToken<Set<NodeSummary>>() {
}.getType();

private final Set<NodeSummary> allNodes;

Expand Down Expand Up @@ -79,8 +82,6 @@ private static DistributorStatus fromJson(JsonInput input) {
}

public static class NodeSummary {
private static final Type STEREOTYPES_TYPE =
new TypeToken<Map<Capabilities, Integer>>() {}.getType();

private final UUID nodeId;
private final URI uri;
Expand Down Expand Up @@ -141,6 +142,26 @@ public boolean hasCapacity() {
.orElse(false);
}

private Map<String, Object> toJson() {
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
builder.put("nodeId", getNodeId());
builder.put("uri", getUri());
builder.put("up", isUp());
builder.put("maxSessionCount", getMaxSessionCount());
builder.put("stereotypes", getStereotypes().entrySet().stream()
.map(entry -> ImmutableMap.of(
"capabilities", entry.getKey(),
"count", entry.getValue()))
.collect(toImmutableList()));
builder.put("usedStereotypes", getUsedStereotypes().entrySet().stream()
.map(entry -> ImmutableMap.of(
"capabilities", entry.getKey(),
"count", entry.getValue()))
.collect(toImmutableList()));

return builder.build();
}

private static NodeSummary fromJson(JsonInput input) {
UUID nodeId = null;
URI uri = null;
Expand All @@ -161,7 +182,7 @@ private static NodeSummary fromJson(JsonInput input) {
break;

case "stereotypes":
stereotypes = input.read(STEREOTYPES_TYPE);
stereotypes = readCapabilityCounts(input);
break;

case "up":
Expand All @@ -173,17 +194,50 @@ private static NodeSummary fromJson(JsonInput input) {
break;

case "usedStereotypes":
used = input.read(STEREOTYPES_TYPE);
used = readCapabilityCounts(input);
break;

default:
input.skipValue();
break;
}
}

input.endObject();

return new NodeSummary(nodeId, uri, up, maxSessionCount, stereotypes, used);
}

private static Map<Capabilities, Integer> readCapabilityCounts(JsonInput input) {
Map<Capabilities, Integer> toReturn = new HashMap<>();

input.beginArray();
while (input.hasNext()) {
Capabilities caps = null;
int count = 0;
input.beginObject();
while (input.hasNext()) {
switch (input.nextName()) {
case "capabilities":
caps = input.read(Capabilities.class);
break;

case "count":
count = input.nextNumber().intValue();
break;

default:
input.skipValue();
break;
}
}
input.endObject();

toReturn.put(caps, count);
}
input.endArray();

return toReturn;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@
import org.openqa.selenium.grid.server.HelpFlags;
import org.openqa.selenium.grid.server.Server;
import org.openqa.selenium.grid.server.W3CCommandHandler;
import org.openqa.selenium.grid.sessionmap.SessionMap;
import org.openqa.selenium.grid.sessionmap.config.SessionMapFlags;
import org.openqa.selenium.grid.sessionmap.config.SessionMapOptions;
import org.openqa.selenium.grid.web.Routes;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.tracing.DistributedTracer;
Expand Down Expand Up @@ -107,11 +109,15 @@ public Executable configure(String... args) {
EventBusConfig events = new EventBusConfig(config);
EventBus bus = events.getEventBus();

HttpClient.Factory clientFactory = HttpClient.Factory.createDefault();

SessionMap sessions = new SessionMapOptions(config).getSessionMap(clientFactory);

Distributor distributor = new LocalDistributor(
tracer,
bus,
HttpClient.Factory.createDefault(),
null);
clientFactory,
sessions);

BaseServerOptions serverOptions = new BaseServerOptions(config);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.openqa.selenium.grid.distributor.local;

import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.stream.Collectors.toList;
import static org.openqa.selenium.grid.distributor.local.Host.Status.UP;

import com.google.common.annotations.VisibleForTesting;
Expand Down Expand Up @@ -57,6 +58,7 @@
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class LocalDistributor extends Distributor {

Expand Down Expand Up @@ -112,7 +114,8 @@ public Session newSession(NewSessionPayload payload) throws SessionNotCreatedExc

Session session = selected
.orElseThrow(
() -> new SessionNotCreatedException("Unable to find provider for session: " + allCaps))
() -> new SessionNotCreatedException(
"Unable to find provider for session: " + payload.stream().collect(toList())))
.get();

sessions.add(session);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ public GridStatusHandler(Json json, HttpClient.Factory clientFactory, Distributo

@Override
public void execute(HttpRequest req, HttpResponse resp) throws IOException {
DistributorStatus status = null;
long start = System.currentTimeMillis();

DistributorStatus status;
try {
status = EXECUTOR_SERVICE.submit(distributor::getStatus).get(2, SECONDS);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
Expand All @@ -91,7 +93,6 @@ public void execute(HttpRequest req, HttpResponse resp) throws IOException {
return;
}

long start = System.currentTimeMillis();
boolean ready = status.hasCapacity();
String message = ready ? "Selenium Grid ready." : "Selenium Grid not ready";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@
import static com.google.common.net.MediaType.JSON_UTF_8;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableMap;

import org.openqa.selenium.grid.web.CommandHandler;
import org.openqa.selenium.grid.web.ErrorCodec;
import org.openqa.selenium.json.Json;
import org.openqa.selenium.remote.ErrorCodes;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;

Expand All @@ -34,7 +32,7 @@
public class W3CCommandHandler implements CommandHandler {

public static final Json JSON = new Json();
private final ErrorCodes errors = new ErrorCodes();
private final ErrorCodec errors = ErrorCodec.createDefault();
private final CommandHandler delegate;

public W3CCommandHandler(CommandHandler delegate) {
Expand All @@ -50,16 +48,12 @@ public void execute(HttpRequest req, HttpResponse resp) throws IOException {
try {
delegate.execute(req, resp);
} catch (Throwable cause) {
// Fair enough. Attempt to convert the exception to something useful.
resp.setStatus(errors.getHttpStatusCode(cause));

resp.setHeader("Content-Type", JSON_UTF_8.toString());
resp.setHeader("Cache-Control", "none");

resp.setContent(JSON.toJson(
ImmutableMap.of(
"status", errors.toStatusCode(cause),
"value", cause)).getBytes(UTF_8));
resp.setContent(JSON.toJson(errors.encode(cause)).getBytes(UTF_8));
}
}
}

0 comments on commit fe4451e

Please sign in to comment.