Skip to content

Commit 8943c61

Browse files
committed
Fix failing tests for Grid registration
1 parent 824de2a commit 8943c61

File tree

13 files changed

+273
-167
lines changed

13 files changed

+273
-167
lines changed

java/client/src/org/openqa/selenium/json/BooleanCoercer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class BooleanCoercer extends TypeCoercer<Boolean> {
2424

2525
@Override
2626
public boolean test(Class<?> aClass) {
27-
return Boolean.class.isAssignableFrom(aClass);
27+
return Boolean.class.isAssignableFrom(aClass) || boolean.class.isAssignableFrom(aClass);
2828
}
2929

3030
@Override

java/client/src/org/openqa/selenium/json/JsonInput.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
import java.io.Closeable;
2525
import java.lang.reflect.Type;
26-
import java.util.Collection;
26+
import java.util.Arrays;
2727
import java.util.Objects;
2828
import java.util.concurrent.Callable;
2929

@@ -47,6 +47,10 @@ public JsonInput propertySetting(PropertySetting setter) {
4747
return this;
4848
}
4949

50+
public JsonInput addCoercers(TypeCoercer<?>... coercers) {
51+
return addCoercers(Arrays.asList(coercers));
52+
}
53+
5054
public JsonInput addCoercers(Iterable<TypeCoercer<?>> coercers) {
5155
synchronized (this) {
5256
if (readPerformed) {

java/client/src/org/openqa/selenium/json/JsonTypeCoercer.java

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
import org.openqa.selenium.MutableCapabilities;
2828

2929
import java.lang.reflect.Type;
30+
import java.util.ArrayList;
3031
import java.util.HashSet;
3132
import java.util.LinkedHashMap;
32-
import java.util.LinkedList;
3333
import java.util.List;
3434
import java.util.Map;
3535
import java.util.Objects;
@@ -41,13 +41,29 @@
4141

4242
class JsonTypeCoercer {
4343

44+
private final Set<TypeCoercer<?>> additionalCoercers;
4445
private final Set<TypeCoercer> coercers;
4546
private final Map<Type, BiFunction<JsonInput, PropertySetting, Object>> knownCoercers = new ConcurrentHashMap<>();
4647

4748
JsonTypeCoercer() {
48-
coercers =
49+
this(ImmutableSet.of());
50+
}
51+
52+
JsonTypeCoercer(JsonTypeCoercer coercer, Iterable<TypeCoercer<?>> coercers) {
53+
this(
54+
ImmutableSet.<TypeCoercer<?>>builder()
55+
.addAll(coercers)
56+
.addAll(coercer.additionalCoercers)
57+
.build());
58+
}
59+
60+
JsonTypeCoercer(Iterable<TypeCoercer<?>> coercers) {
61+
this.additionalCoercers = ImmutableSet.copyOf(coercers);
62+
63+
this.coercers =
4964
// Note: we call out when ordering matters.
5065
ImmutableSet.<TypeCoercer>builder()
66+
.addAll(coercers)
5167
// Types that don't contain other types first
5268
// From java
5369
.add(new BooleanCoercer())
@@ -80,7 +96,7 @@ class JsonTypeCoercer {
8096
.add(new SessionIdCoercer())
8197

8298
// Container types
83-
.add(new CollectionCoercer<>(List.class, this, Collectors.toCollection(LinkedList::new)))
99+
.add(new CollectionCoercer<>(List.class, this, Collectors.toCollection(ArrayList::new)))
84100
.add(new CollectionCoercer<>(Set.class, this, Collectors.toCollection(HashSet::new)))
85101

86102
.add(new MapCoercer<>(
@@ -98,13 +114,6 @@ class JsonTypeCoercer {
98114
.build();
99115
}
100116

101-
JsonTypeCoercer(JsonTypeCoercer coercer, Iterable<TypeCoercer<?>> coercers) {
102-
this.coercers = ImmutableSet.<TypeCoercer>builder()
103-
.addAll(coercers)
104-
.addAll(coercer.coercers)
105-
.build();
106-
}
107-
108117
<T> T coerce(JsonInput json, Type typeOfT, PropertySetting setter) {
109118
BiFunction<JsonInput, PropertySetting, Object> coercer =
110119
knownCoercers.computeIfAbsent(typeOfT, this::buildCoercer);
@@ -120,15 +129,18 @@ private BiFunction<JsonInput, PropertySetting, Object> buildCoercer(Type type) {
120129
.filter(coercer -> coercer.test(narrow(type)))
121130
.findFirst()
122131
.map(coercer -> coercer.apply(type))
123-
.map(func -> (BiFunction<JsonInput, PropertySetting, Object>) (jsonInput, setter) -> {
124-
if (jsonInput.peek() == JsonType.NULL) {
125-
jsonInput.skipValue();
126-
return null;
127-
}
128-
129-
//noinspection unchecked
130-
return func.apply(jsonInput, setter);
131-
})
132+
.map(
133+
func ->
134+
(BiFunction<JsonInput, PropertySetting, Object>)
135+
(jsonInput, setter) -> {
136+
if (jsonInput.peek() == JsonType.NULL) {
137+
jsonInput.skipValue();
138+
return null;
139+
}
140+
141+
//noinspection unchecked
142+
return func.apply(jsonInput, setter);
143+
})
132144
.orElseThrow(() -> new JsonException("Unable to find type coercer for " + type));
133145
}
134146

java/client/src/org/openqa/selenium/json/NumberCoercer.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
package org.openqa.selenium.json;
1919

20+
import com.google.common.primitives.Primitives;
21+
2022
import java.lang.reflect.Type;
2123
import java.util.Objects;
2224
import java.util.function.BiFunction;
@@ -34,7 +36,7 @@ class NumberCoercer<T extends Number> extends TypeCoercer<T> {
3436

3537
@Override
3638
public boolean test(Class<?> type) {
37-
return stereotype.isAssignableFrom(type);
39+
return stereotype.isAssignableFrom(Primitives.wrap(type));
3840
}
3941

4042
@Override
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package org.openqa.grid.common;
2+
3+
import org.openqa.grid.internal.listeners.Prioritizer;
4+
import org.openqa.grid.internal.utils.CapabilityMatcher;
5+
import org.openqa.selenium.json.Json;
6+
import org.openqa.selenium.json.JsonException;
7+
import org.openqa.selenium.json.JsonInput;
8+
import org.openqa.selenium.json.PropertySetting;
9+
import org.openqa.selenium.json.TypeCoercer;
10+
11+
import java.io.IOException;
12+
import java.io.Reader;
13+
import java.io.StringReader;
14+
import java.io.UncheckedIOException;
15+
import java.lang.reflect.Type;
16+
import java.util.function.BiFunction;
17+
18+
public class GridConfiguredJson {
19+
20+
private final static Json JSON = new Json();
21+
22+
private GridConfiguredJson() {
23+
// Utility class
24+
}
25+
26+
public static <T> T toType(String json, Type typeOfT) {
27+
try (Reader reader = new StringReader(json);
28+
JsonInput jsonInput = JSON.newInput(reader)) {
29+
return toType(jsonInput, typeOfT);
30+
} catch (IOException e) {
31+
throw new UncheckedIOException(e);
32+
}
33+
}
34+
35+
public static <T> T toType(JsonInput jsonInput, Type typeOfT) {
36+
return jsonInput
37+
.propertySetting(PropertySetting.BY_FIELD)
38+
.addCoercers(new CapabilityMatcherCoercer(), new PrioritizerCoercer())
39+
.read(typeOfT);
40+
}
41+
42+
private static class SimpleClassNameCoercer<T> extends TypeCoercer<T> {
43+
44+
private final Class<?> stereotype;
45+
46+
protected SimpleClassNameCoercer(Class<?> stereotype) {
47+
this.stereotype = stereotype;
48+
}
49+
50+
@Override
51+
public boolean test(Class<?> aClass) {
52+
return stereotype.isAssignableFrom(aClass);
53+
}
54+
55+
@Override
56+
public BiFunction<JsonInput, PropertySetting, T> apply(Type type) {
57+
return (jsonInput, setting) -> {
58+
String clazz = jsonInput.nextString();
59+
try {
60+
return (T) Class.forName(clazz).asSubclass(stereotype).newInstance();
61+
} catch (ReflectiveOperationException e) {
62+
throw new JsonException(String.format("%s could not be coerced to instance", clazz));
63+
}
64+
};
65+
}
66+
}
67+
68+
private static class CapabilityMatcherCoercer extends SimpleClassNameCoercer<CapabilityMatcher> {
69+
protected CapabilityMatcherCoercer() {
70+
super(CapabilityMatcher.class);
71+
}
72+
}
73+
74+
private static class PrioritizerCoercer extends SimpleClassNameCoercer<Prioritizer> {
75+
protected PrioritizerCoercer() {
76+
super(Prioritizer.class);
77+
}
78+
}
79+
80+
81+
}

java/server/src/org/openqa/grid/common/RegistrationRequest.java

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,16 @@
1717

1818
package org.openqa.grid.common;
1919

20-
import com.google.common.reflect.TypeToken;
21-
import com.google.gson.GsonBuilder;
22-
import com.google.gson.JsonObject;
23-
import com.google.gson.JsonSyntaxException;
20+
import static org.openqa.selenium.json.Json.MAP_TYPE;
21+
2422
import com.google.gson.annotations.Expose;
2523
import com.google.gson.annotations.SerializedName;
2624

2725
import org.openqa.grid.common.exception.GridConfigurationException;
2826
import org.openqa.grid.internal.utils.configuration.GridNodeConfiguration;
29-
import org.openqa.grid.internal.utils.configuration.GridNodeConfiguration.CollectionOfDesiredCapabilitiesDeSerializer;
30-
import org.openqa.selenium.MutableCapabilities;
27+
import org.openqa.selenium.json.Json;
28+
import org.openqa.selenium.json.JsonException;
3129

32-
import java.util.List;
3330
import java.util.Map;
3431
import java.util.TreeMap;
3532

@@ -127,36 +124,32 @@ public Map<String, Object> toJson() {
127124
return json;
128125
}
129126

130-
/**
131-
* Create an object from a registration request formatted as a JsonObject
132-
*
133-
* @param json JsonObject
134-
* @return
135-
*/
136-
public static RegistrationRequest fromJson(JsonObject json) throws JsonSyntaxException {
137-
GsonBuilder builder = new GsonBuilder();
138-
builder.registerTypeAdapter(new TypeToken<List<MutableCapabilities>>(){}.getType(),
139-
new CollectionOfDesiredCapabilitiesDeSerializer());
140-
141-
RegistrationRequest request = builder.excludeFieldsWithoutExposeAnnotation().create()
142-
.fromJson(json, RegistrationRequest.class);
143-
144-
return request;
145-
}
146-
147127
/**
148128
* Create an object from a registration request formatted as a json string.
149129
*
150-
* @param json JSON String
130+
* @param jsonString JSON String
151131
* @return
152132
*/
153-
public static RegistrationRequest fromJson(String json) throws JsonSyntaxException {
154-
GsonBuilder builder = new GsonBuilder();
155-
builder.registerTypeAdapter(new TypeToken<List<MutableCapabilities>>(){}.getType(),
156-
new CollectionOfDesiredCapabilitiesDeSerializer());
133+
public static RegistrationRequest fromJson(String jsonString) throws JsonException {
134+
// If we could, we'd just get Json to coerce this for us, but that would lead to endless
135+
// recursion as the first thing it would do would be to call this very method. *sigh*
136+
Json json = new Json();
137+
Map<String, Object> raw = json.toType(jsonString, MAP_TYPE);
138+
RegistrationRequest request = new RegistrationRequest();
139+
140+
if (raw.get("name") instanceof String) {
141+
request.name = (String) raw.get("name");
142+
}
157143

158-
RegistrationRequest request = builder.excludeFieldsWithoutExposeAnnotation().create()
159-
.fromJson(json, RegistrationRequest.class);
144+
if (raw.get("description") instanceof String) {
145+
request.description = (String) raw.get("description");
146+
}
147+
148+
if (raw.get("configuration") instanceof Map) {
149+
// This is nasty. Look away now!
150+
String converted = json.toJson(raw.get("configuration"));
151+
request.configuration = GridConfiguredJson.toType(converted, GridNodeConfiguration.class);
152+
}
160153

161154
return request;
162155
}

0 commit comments

Comments
 (0)