mirror of https://github.com/hyperledger/besu
[PIE-1809] Clean up genesis parsing (#1809)
Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>pull/2/head
parent
75b754e36b
commit
63ffdb5f02
@ -1,45 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2019 ConsenSys AG. |
|
||||||
* |
|
||||||
* 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 tech.pegasys.pantheon.config; |
|
||||||
|
|
||||||
import java.math.BigInteger; |
|
||||||
import java.util.Optional; |
|
||||||
import java.util.OptionalLong; |
|
||||||
|
|
||||||
import io.vertx.core.json.JsonObject; |
|
||||||
|
|
||||||
public class ConfigUtil { |
|
||||||
public static OptionalLong getOptionalLong(final JsonObject jsonObject, final String key) { |
|
||||||
return jsonObject.containsKey(key) |
|
||||||
? OptionalLong.of(jsonObject.getLong(key)) |
|
||||||
: OptionalLong.empty(); |
|
||||||
} |
|
||||||
|
|
||||||
public static Optional<BigInteger> getOptionalBigInteger( |
|
||||||
final JsonObject jsonObject, final String key) { |
|
||||||
return jsonObject.containsKey(key) |
|
||||||
? Optional.ofNullable(getBigInteger(jsonObject, key)) |
|
||||||
: Optional.empty(); |
|
||||||
} |
|
||||||
|
|
||||||
private static BigInteger getBigInteger(final JsonObject jsonObject, final String key) { |
|
||||||
final Number value = (Number) jsonObject.getMap().get(key); |
|
||||||
if (value == null) { |
|
||||||
return null; |
|
||||||
} else if (value instanceof BigInteger) { |
|
||||||
return (BigInteger) value; |
|
||||||
} else { |
|
||||||
return BigInteger.valueOf(value.longValue()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,243 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2019 ConsenSys AG. |
||||||
|
* |
||||||
|
* 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 tech.pegasys.pantheon.config; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.OptionalInt; |
||||||
|
import java.util.OptionalLong; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser.Feature; |
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode; |
||||||
|
import com.fasterxml.jackson.databind.node.JsonNodeType; |
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||||
|
|
||||||
|
public class JsonUtil { |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the string representation of the value at {@code key}. For example, a numeric value like 5 |
||||||
|
* will be returned as "5". |
||||||
|
* |
||||||
|
* @param node The {@code ObjectNode} from which the value will be extracted. |
||||||
|
* @param key The key corresponding to the value to extract. |
||||||
|
* @return The value at the given key as a string if it exists. |
||||||
|
*/ |
||||||
|
public static Optional<String> getValueAsString(final ObjectNode node, final String key) { |
||||||
|
return getValue(node, key).map(JsonNode::asText); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the string representation of the value at {@code key}. For example, a numeric value like 5 |
||||||
|
* will be returned as "5". |
||||||
|
* |
||||||
|
* @param node The {@code ObjectNode} from which the value will be extracted. |
||||||
|
* @param key The key corresponding to the value to extract. |
||||||
|
* @param defaultValue The value to return if no value is found at {@code key}. |
||||||
|
* @return The value at the given key as a string if it exists, otherwise {@code defaultValue} |
||||||
|
*/ |
||||||
|
public static String getValueAsString( |
||||||
|
final ObjectNode node, final String key, final String defaultValue) { |
||||||
|
return getValueAsString(node, key).orElse(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns textual (string) value at {@code key}. See {@link #getValueAsString} for retrieving |
||||||
|
* non-textual values in string form. |
||||||
|
* |
||||||
|
* @param node The {@code ObjectNode} from which the value will be extracted. |
||||||
|
* @param key The key corresponding to the value to extract. |
||||||
|
* @return The textual value at {@code key} if it exists. |
||||||
|
*/ |
||||||
|
public static Optional<String> getString(final ObjectNode node, final String key) { |
||||||
|
return getValue(node, key) |
||||||
|
.filter(jsonNode -> validateType(jsonNode, JsonNodeType.STRING)) |
||||||
|
.map(JsonNode::asText); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns textual (string) value at {@code key}. See {@link #getValueAsString} for retrieving |
||||||
|
* non-textual values in string form. |
||||||
|
* |
||||||
|
* @param node The {@code ObjectNode} from which the value will be extracted. |
||||||
|
* @param key The key corresponding to the value to extract. |
||||||
|
* @param defaultValue The value to return if no value is found at {@code key}. |
||||||
|
* @return The textual value at {@code key} if it exists, otherwise {@code defaultValue} |
||||||
|
*/ |
||||||
|
public static String getString( |
||||||
|
final ObjectNode node, final String key, final String defaultValue) { |
||||||
|
return getString(node, key).orElse(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
public static OptionalInt getInt(final ObjectNode node, final String key) { |
||||||
|
return getValue(node, key) |
||||||
|
.filter(jsonNode -> validateType(jsonNode, JsonNodeType.NUMBER)) |
||||||
|
.filter(JsonUtil::validateInt) |
||||||
|
.map(JsonNode::asInt) |
||||||
|
.map(OptionalInt::of) |
||||||
|
.orElse(OptionalInt.empty()); |
||||||
|
} |
||||||
|
|
||||||
|
public static int getInt(final ObjectNode node, final String key, final int defaultValue) { |
||||||
|
return getInt(node, key).orElse(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
public static OptionalLong getLong(final ObjectNode json, final String key) { |
||||||
|
return getValue(json, key) |
||||||
|
.filter(jsonNode -> validateType(jsonNode, JsonNodeType.NUMBER)) |
||||||
|
.filter(JsonUtil::validateLong) |
||||||
|
.map(JsonNode::asLong) |
||||||
|
.map(OptionalLong::of) |
||||||
|
.orElse(OptionalLong.empty()); |
||||||
|
} |
||||||
|
|
||||||
|
public static long getLong(final ObjectNode json, final String key, final long defaultValue) { |
||||||
|
return getLong(json, key).orElse(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
public static Optional<Boolean> getBoolean(final ObjectNode node, final String key) { |
||||||
|
return getValue(node, key) |
||||||
|
.filter(jsonNode -> validateType(jsonNode, JsonNodeType.BOOLEAN)) |
||||||
|
.map(JsonNode::asBoolean); |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean getBoolean( |
||||||
|
final ObjectNode node, final String key, final boolean defaultValue) { |
||||||
|
return getBoolean(node, key).orElse(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
public static ObjectNode createEmptyObjectNode() { |
||||||
|
ObjectMapper mapper = getObjectMapper(); |
||||||
|
return mapper.createObjectNode(); |
||||||
|
} |
||||||
|
|
||||||
|
public static ObjectNode objectNodeFromMap(final Map<String, Object> map) { |
||||||
|
return (ObjectNode) getObjectMapper().valueToTree(map); |
||||||
|
} |
||||||
|
|
||||||
|
public static ObjectNode objectNodeFromString(final String jsonData) { |
||||||
|
return objectNodeFromString(jsonData, false); |
||||||
|
} |
||||||
|
|
||||||
|
public static ObjectNode objectNodeFromString( |
||||||
|
final String jsonData, final boolean allowComments) { |
||||||
|
final ObjectMapper objectMapper = new ObjectMapper(); |
||||||
|
objectMapper.configure(Feature.ALLOW_COMMENTS, allowComments); |
||||||
|
try { |
||||||
|
final JsonNode jsonNode = objectMapper.readTree(jsonData); |
||||||
|
validateType(jsonNode, JsonNodeType.OBJECT); |
||||||
|
return (ObjectNode) jsonNode; |
||||||
|
} catch (IOException e) { |
||||||
|
// Reading directly from a string should not raise an IOException, just catch and rethrow
|
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static String getJson(final Object objectNode) throws JsonProcessingException { |
||||||
|
return getJson(objectNode, true); |
||||||
|
} |
||||||
|
|
||||||
|
public static String getJson(final Object objectNode, final boolean prettyPrint) |
||||||
|
throws JsonProcessingException { |
||||||
|
ObjectMapper mapper = getObjectMapper(); |
||||||
|
if (prettyPrint) { |
||||||
|
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectNode); |
||||||
|
} else { |
||||||
|
return mapper.writeValueAsString(objectNode); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static ObjectMapper getObjectMapper() { |
||||||
|
return new ObjectMapper(); |
||||||
|
} |
||||||
|
|
||||||
|
public static Optional<ObjectNode> getObjectNode(final ObjectNode json, final String fieldKey) { |
||||||
|
return getObjectNode(json, fieldKey, true); |
||||||
|
} |
||||||
|
|
||||||
|
public static Optional<ObjectNode> getObjectNode( |
||||||
|
final ObjectNode json, final String fieldKey, final boolean strict) { |
||||||
|
final JsonNode obj = json.get(fieldKey); |
||||||
|
if (obj == null || obj.isNull()) { |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
|
||||||
|
if (!obj.isObject()) { |
||||||
|
if (strict) { |
||||||
|
validateType(obj, JsonNodeType.OBJECT); |
||||||
|
} else { |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return Optional.of((ObjectNode) obj); |
||||||
|
} |
||||||
|
|
||||||
|
public static Optional<ArrayNode> getArrayNode(final ObjectNode json, final String fieldKey) { |
||||||
|
return getArrayNode(json, fieldKey, true); |
||||||
|
} |
||||||
|
|
||||||
|
public static Optional<ArrayNode> getArrayNode( |
||||||
|
final ObjectNode json, final String fieldKey, final boolean strict) { |
||||||
|
final JsonNode obj = json.get(fieldKey); |
||||||
|
if (obj == null || obj.isNull()) { |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
|
||||||
|
if (!obj.isArray()) { |
||||||
|
if (strict) { |
||||||
|
validateType(obj, JsonNodeType.ARRAY); |
||||||
|
} else { |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return Optional.of((ArrayNode) obj); |
||||||
|
} |
||||||
|
|
||||||
|
private static Optional<JsonNode> getValue(final ObjectNode node, final String key) { |
||||||
|
JsonNode jsonNode = node.get(key); |
||||||
|
if (jsonNode == null || jsonNode.isNull()) { |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
return Optional.of(jsonNode); |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean validateType(final JsonNode node, final JsonNodeType expectedType) { |
||||||
|
if (node.getNodeType() != expectedType) { |
||||||
|
final String errorMessage = |
||||||
|
String.format( |
||||||
|
"Expected %s value but got %s", |
||||||
|
expectedType.toString().toLowerCase(), node.getNodeType().toString().toLowerCase()); |
||||||
|
throw new IllegalArgumentException(errorMessage); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean validateLong(final JsonNode node) { |
||||||
|
if (!node.canConvertToLong()) { |
||||||
|
throw new IllegalArgumentException("Cannot convert value to long: " + node.toString()); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean validateInt(final JsonNode node) { |
||||||
|
if (!node.canConvertToInt()) { |
||||||
|
throw new IllegalArgumentException("Cannot convert value to integer: " + node.toString()); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,545 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2019 ConsenSys AG. |
||||||
|
* |
||||||
|
* 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 tech.pegasys.pantheon.config; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.OptionalInt; |
||||||
|
import java.util.OptionalLong; |
||||||
|
import java.util.TreeMap; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParseException; |
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode; |
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class JsonUtilTest { |
||||||
|
private ObjectMapper mapper = new ObjectMapper(); |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getLong_nonExistentKey() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
final OptionalLong result = JsonUtil.getLong(node, "test"); |
||||||
|
assertThat(result).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getLong_nullValue() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.set("test", null); |
||||||
|
final OptionalLong result = JsonUtil.getLong(node, "test"); |
||||||
|
assertThat(result).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getLong_validValue() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.put("test", Long.MAX_VALUE); |
||||||
|
final OptionalLong result = JsonUtil.getLong(node, "test"); |
||||||
|
assertThat(result).hasValue(Long.MAX_VALUE); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getLong_overflowingValue() { |
||||||
|
final String overflowingValue = Long.toString(Long.MAX_VALUE, 10) + "100"; |
||||||
|
final String jsonStr = "{\"test\": " + overflowingValue + " }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getLong(rootNode, "test")) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Cannot convert value to long: " + overflowingValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getLong_wrongType() { |
||||||
|
final String jsonStr = "{\"test\": \"bla\" }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getLong(rootNode, "test")) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Expected number value but got string"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getLong_nullValue_withDefault() { |
||||||
|
final long defaultValue = 11; |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.set("test", null); |
||||||
|
final long result = JsonUtil.getLong(node, "test", defaultValue); |
||||||
|
assertThat(result).isEqualTo(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getLong_nonExistentKey_withDefault() { |
||||||
|
final long defaultValue = 11; |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
final long result = JsonUtil.getLong(node, "test", defaultValue); |
||||||
|
assertThat(result).isEqualTo(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getLong_validValue_withDefault() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.put("test", Long.MAX_VALUE); |
||||||
|
final long result = JsonUtil.getLong(node, "test", 11); |
||||||
|
assertThat(result).isEqualTo(Long.MAX_VALUE); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getLong_overflowingValue_withDefault() { |
||||||
|
final String overflowingValue = Long.toString(Long.MAX_VALUE, 10) + "100"; |
||||||
|
final String jsonStr = "{\"test\": " + overflowingValue + " }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getLong(rootNode, "test", 11)) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Cannot convert value to long: " + overflowingValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getLong_wrongType_withDefault() { |
||||||
|
final String jsonStr = "{\"test\": \"bla\" }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getLong(rootNode, "test", 11)) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Expected number value but got string"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getInt_nonExistentKey() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
final OptionalInt result = JsonUtil.getInt(node, "test"); |
||||||
|
assertThat(result).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getInt_nullValue() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.set("test", null); |
||||||
|
final OptionalInt result = JsonUtil.getInt(node, "test"); |
||||||
|
assertThat(result).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getInt_validValue() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.put("test", Integer.MAX_VALUE); |
||||||
|
final OptionalInt result = JsonUtil.getInt(node, "test"); |
||||||
|
assertThat(result).hasValue(Integer.MAX_VALUE); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getInt_overflowingValue() { |
||||||
|
final String overflowingValue = Integer.toString(Integer.MAX_VALUE, 10) + "100"; |
||||||
|
final String jsonStr = "{\"test\": " + overflowingValue + " }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getInt(rootNode, "test")) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Cannot convert value to integer: " + overflowingValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getInt_wrongType() { |
||||||
|
final String jsonStr = "{\"test\": \"bla\" }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getInt(rootNode, "test")) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Expected number value but got string"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getInt_nullValue_withDefault() { |
||||||
|
final int defaultValue = 11; |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.set("test", null); |
||||||
|
final int result = JsonUtil.getInt(node, "test", defaultValue); |
||||||
|
assertThat(result).isEqualTo(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getInt_nonExistentKey_withDefault() { |
||||||
|
final int defaultValue = 11; |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
final int result = JsonUtil.getInt(node, "test", defaultValue); |
||||||
|
assertThat(result).isEqualTo(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getInt_validValue_withDefault() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.put("test", Integer.MAX_VALUE); |
||||||
|
final int result = JsonUtil.getInt(node, "test", 11); |
||||||
|
assertThat(result).isEqualTo(Integer.MAX_VALUE); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getInt_overflowingValue_withDefault() { |
||||||
|
final String overflowingValue = Integer.toString(Integer.MAX_VALUE, 10) + "100"; |
||||||
|
final String jsonStr = "{\"test\": " + overflowingValue + " }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getInt(rootNode, "test", 11)) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Cannot convert value to integer: " + overflowingValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getInt_wrongType_withDefault() { |
||||||
|
final String jsonStr = "{\"test\": \"bla\" }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getInt(rootNode, "test", 11)) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Expected number value but got string"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getString_nonExistentKey() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
final Optional<String> result = JsonUtil.getString(node, "test"); |
||||||
|
assertThat(result).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getString_nullValue() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.set("test", null); |
||||||
|
final Optional<String> result = JsonUtil.getString(node, "test"); |
||||||
|
assertThat(result).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getString_validValue() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.put("test", "bla"); |
||||||
|
final Optional<String> result = JsonUtil.getString(node, "test"); |
||||||
|
assertThat(result).hasValue("bla"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getString_wrongType() { |
||||||
|
final String jsonStr = "{\"test\": 123 }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getString(rootNode, "test")) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Expected string value but got number"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getString_nullValue_withDefault() { |
||||||
|
final String defaultValue = "bla"; |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.set("test", null); |
||||||
|
final String result = JsonUtil.getString(node, "test", defaultValue); |
||||||
|
assertThat(result).isEqualTo(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getString_nonExistentKey_withDefault() { |
||||||
|
final String defaultValue = "bla"; |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
final String result = JsonUtil.getString(node, "test", defaultValue); |
||||||
|
assertThat(result).isEqualTo(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getString_validValue_withDefault() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.put("test", "bla"); |
||||||
|
final String result = JsonUtil.getString(node, "test", "11"); |
||||||
|
assertThat(result).isEqualTo("bla"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getValueAsString_nonExistentKey() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
final Optional<String> result = JsonUtil.getValueAsString(node, "test"); |
||||||
|
assertThat(result).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getValueAsString_nullValue() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.set("test", null); |
||||||
|
final Optional<String> result = JsonUtil.getValueAsString(node, "test"); |
||||||
|
assertThat(result).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getValueAsString_stringValue() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.put("test", "bla"); |
||||||
|
final Optional<String> result = JsonUtil.getValueAsString(node, "test"); |
||||||
|
assertThat(result).hasValue("bla"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getValueAsString_nonStringValue() { |
||||||
|
final String jsonStr = "{\"test\": 123 }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
final Optional<String> result = JsonUtil.getValueAsString(rootNode, "test"); |
||||||
|
assertThat(result).hasValue("123"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getValueAsString_nullValue_withDefault() { |
||||||
|
final String defaultValue = "bla"; |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.set("test", null); |
||||||
|
final String result = JsonUtil.getValueAsString(node, "test", defaultValue); |
||||||
|
assertThat(result).isEqualTo(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getValueAsString_nonExistentKey_withDefault() { |
||||||
|
final String defaultValue = "bla"; |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
final String result = JsonUtil.getValueAsString(node, "test", defaultValue); |
||||||
|
assertThat(result).isEqualTo(defaultValue); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getValueAsString_stringValue_withDefault() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.put("test", "bla"); |
||||||
|
final String result = JsonUtil.getValueAsString(node, "test", "11"); |
||||||
|
assertThat(result).isEqualTo("bla"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getValueAsString_nonStringValue_withDefault() { |
||||||
|
final String jsonStr = "{\"test\": 123 }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
final String result = JsonUtil.getValueAsString(rootNode, "test", "11"); |
||||||
|
assertThat(result).isEqualTo("123"); |
||||||
|
} |
||||||
|
|
||||||
|
// Boolean
|
||||||
|
@Test |
||||||
|
public void getBoolean_nonExistentKey() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
final Optional<Boolean> result = JsonUtil.getBoolean(node, "test"); |
||||||
|
assertThat(result).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getBoolean_nullValue() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.set("test", null); |
||||||
|
final Optional<Boolean> result = JsonUtil.getBoolean(node, "test"); |
||||||
|
assertThat(result).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getBoolean_validValue() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.put("test", true); |
||||||
|
final Optional<Boolean> result = JsonUtil.getBoolean(node, "test"); |
||||||
|
assertThat(result).hasValue(true); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getBoolean_wrongType() { |
||||||
|
final String jsonStr = "{\"test\": 123 }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getBoolean(rootNode, "test")) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Expected boolean value but got number"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getBoolean_nullValue_withDefault() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.set("test", null); |
||||||
|
final Boolean result = JsonUtil.getBoolean(node, "test", false); |
||||||
|
assertThat(result).isEqualTo(false); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getBoolean_nonExistentKey_withDefault() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
final Boolean result = JsonUtil.getBoolean(node, "test", true); |
||||||
|
assertThat(result).isEqualTo(true); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getBoolean_validValue_withDefault() { |
||||||
|
final ObjectNode node = mapper.createObjectNode(); |
||||||
|
node.put("test", false); |
||||||
|
final Boolean result = JsonUtil.getBoolean(node, "test", true); |
||||||
|
assertThat(result).isEqualTo(false); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getBoolean_wrongType_withDefault() { |
||||||
|
final String jsonStr = "{\"test\": 123 }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getBoolean(rootNode, "test", true)) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Expected boolean value but got number"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void objectNodeFromMap() { |
||||||
|
final Map<String, Object> map = new TreeMap<>(); |
||||||
|
map.put("a", 1); |
||||||
|
map.put("b", 2); |
||||||
|
|
||||||
|
final Map<String, Object> subMap = new TreeMap<>(); |
||||||
|
subMap.put("c", "bla"); |
||||||
|
subMap.put("d", 2L); |
||||||
|
map.put("subtree", subMap); |
||||||
|
|
||||||
|
ObjectNode node = JsonUtil.objectNodeFromMap(map); |
||||||
|
assertThat(node.get("a").asInt()).isEqualTo(1); |
||||||
|
assertThat(node.get("b").asInt()).isEqualTo(2); |
||||||
|
assertThat(node.get("subtree").get("c").asText()).isEqualTo("bla"); |
||||||
|
assertThat(node.get("subtree").get("d").asLong()).isEqualTo(2L); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void objectNodeFromString() { |
||||||
|
final String jsonStr = "{\"a\":1, \"b\":2}"; |
||||||
|
|
||||||
|
final ObjectNode result = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
assertThat(result.get("a").asInt()).isEqualTo(1); |
||||||
|
assertThat(result.get("b").asInt()).isEqualTo(2); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void objectNodeFromString_withComments_commentsDisabled() { |
||||||
|
final String jsonStr = "// Comment\n{\"a\":1, \"b\":2}"; |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.objectNodeFromString(jsonStr, false)) |
||||||
|
.hasCauseInstanceOf(JsonParseException.class) |
||||||
|
.hasMessageContaining("Unexpected character ('/'"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void objectNodeFromString_withComments_commentsEnabled() { |
||||||
|
final String jsonStr = "// Comment\n{\"a\":1, \"b\":2}"; |
||||||
|
|
||||||
|
final ObjectNode result = JsonUtil.objectNodeFromString(jsonStr, true); |
||||||
|
assertThat(result.get("a").asInt()).isEqualTo(1); |
||||||
|
assertThat(result.get("b").asInt()).isEqualTo(2); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getJson() throws JsonProcessingException { |
||||||
|
final String jsonStr = "{\"a\":1, \"b\":2}"; |
||||||
|
final ObjectNode objectNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
final String resultUgly = JsonUtil.getJson(objectNode, false); |
||||||
|
final String resultPretty = JsonUtil.getJson(objectNode, true); |
||||||
|
|
||||||
|
assertThat(resultUgly).isEqualToIgnoringWhitespace(jsonStr); |
||||||
|
assertThat(resultPretty).isEqualToIgnoringWhitespace(jsonStr); |
||||||
|
// Pretty printed value should have more whitespace and contain returns
|
||||||
|
assertThat(resultPretty.length()).isGreaterThan(resultUgly.length()); |
||||||
|
assertThat(resultPretty).contains("\n"); |
||||||
|
assertThat(resultUgly).doesNotContain("\n"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getObjectNode_validValue() { |
||||||
|
final String jsonStr = "{\"test\": {\"a\":1, \"b\":2} }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
final Optional<ObjectNode> maybeTestNode = JsonUtil.getObjectNode(rootNode, "test"); |
||||||
|
assertThat(maybeTestNode).isNotEmpty(); |
||||||
|
final ObjectNode testNode = maybeTestNode.get(); |
||||||
|
assertThat(testNode.get("a").asInt()).isEqualTo(1); |
||||||
|
assertThat(testNode.get("b").asInt()).isEqualTo(2); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getObjectNode_nullValue() { |
||||||
|
final String jsonStr = "{\"test\": null }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
final Optional<ObjectNode> maybeTestNode = JsonUtil.getObjectNode(rootNode, "test"); |
||||||
|
assertThat(maybeTestNode).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getObjectNode_nonExistentKey() { |
||||||
|
final String jsonStr = "{}"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
final Optional<ObjectNode> maybeTestNode = JsonUtil.getObjectNode(rootNode, "test"); |
||||||
|
assertThat(maybeTestNode).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getObjectNode_wrongNodeType() { |
||||||
|
final String jsonStr = "{\"test\": \"abc\" }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getObjectNode(rootNode, "test")) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Expected object value but got string"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getArrayNode_validValue() { |
||||||
|
final String jsonStr = "{\"test\": [\"a\", \"b\"] }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
final Optional<ArrayNode> maybeTestNode = JsonUtil.getArrayNode(rootNode, "test"); |
||||||
|
assertThat(maybeTestNode).isNotEmpty(); |
||||||
|
final ArrayNode testNode = maybeTestNode.get(); |
||||||
|
assertThat(testNode.get(0).asText()).isEqualTo("a"); |
||||||
|
assertThat(testNode.get(1).asText()).isEqualTo("b"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getArrayNode_nullValue() { |
||||||
|
final String jsonStr = "{\"test\": null }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
final Optional<ArrayNode> maybeTestNode = JsonUtil.getArrayNode(rootNode, "test"); |
||||||
|
assertThat(maybeTestNode).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getArrayNode_nonExistentKey() { |
||||||
|
final String jsonStr = "{}"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
final Optional<ArrayNode> maybeTestNode = JsonUtil.getArrayNode(rootNode, "test"); |
||||||
|
assertThat(maybeTestNode).isEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getArrayNode_wrongNodeType() { |
||||||
|
final String jsonStr = "{\"test\": \"abc\" }"; |
||||||
|
final ObjectNode rootNode = JsonUtil.objectNodeFromString(jsonStr); |
||||||
|
|
||||||
|
assertThatThrownBy(() -> JsonUtil.getArrayNode(rootNode, "test")) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Expected array value but got string"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
{ |
||||||
|
"genesis": { |
||||||
|
"config": { |
||||||
|
"chainId": 2017, |
||||||
|
"constantinoplefixblock": 0, |
||||||
|
"homesteadBlock": 0, |
||||||
|
"eip150Block": 0, |
||||||
|
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", |
||||||
|
"ibft2": { |
||||||
|
|
||||||
|
} |
||||||
|
}, |
||||||
|
"nonce": "0x0", |
||||||
|
"timestamp": "0x5b3c3d18", |
||||||
|
"number": "0x0", |
||||||
|
"gasUsed": "0x0", |
||||||
|
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", |
||||||
|
"gasLimit": "0x47b760", |
||||||
|
"difficulty": "0x1", |
||||||
|
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", |
||||||
|
"coinbase": "0x0000000000000000000000000000000000000000", |
||||||
|
"ibft2": { |
||||||
|
"blockperiodseconds": 2, |
||||||
|
"epochlength": 30000, |
||||||
|
"requesttimeoutseconds": 10 |
||||||
|
}, |
||||||
|
"alloc": { |
||||||
|
"24defc2d149861d3d245749b81fe0e6b28e04f31": { |
||||||
|
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000" |
||||||
|
}, |
||||||
|
"2a813d7db3de19b07f92268b6d4125ed295cbe00": { |
||||||
|
"balance": "0x446c3b15f9926687d2c40534fdb542000000000000" |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"blockchain": { |
||||||
|
"nodes": { |
||||||
|
"keys": [ |
||||||
|
{"invalidObj": "0xb295c4242fb40c6e8ac7b831c916846050f191adc560b8098ba6ad513079571ec1be6e5e1a715857a13a91963097962e048c36c5863014b59e8f67ed3f667680"}, |
||||||
|
"0x6295c4242fb40c6e8ac7b831c916846050f191adc560b8098ba6ad513079571ec1be6e5e1a715857a13a91963097962e048c36c5863014b59e8f67ed3f667680" |
||||||
|
] |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue