Perform minor code clean-up (#2544)

* Perform minor code clean-up

Notable changes:
- Replace most usages of `<code>` with `{@code ...}` in Javadoc
- Add proper summary sentence to `GsonBuilder.enableComplexMapKeySerialization`
- Extend documentation for `GsonBuilder.setDateFormat` methods
- Fix `TypeToken.isAssignableFrom(Type)` throwing AssertionError in some cases
  Maybe the method should not throw an exception in the first place, but it
  might not matter much since it is deprecated already anyway.
- Remove outdated `throws NumberFormatException` from internal
  `JsonReader.nextQuotedValue`; the behavior had been changed by
  85ebaf7c35
- Fix incorrect documentation on JsonScope fields
- Fix unit tests having 'expected' and 'actual' switched
- Use dedicated Truth methods instead of `isTrue()` / `isFalse()`
- Use common helper methods in JsonWriterTest to avoid duplication

* Implement `toString()` for ReflectionAccessFilter constants

* Address most of the review comments

* Add comment about `source.scm.tag=HEAD` warning

Actually it looks like the warning is not actually caused by usage of
`HEAD` as value, but rather because the project has a snapshot version
during development (which is expected though), see
https://github.com/apache/maven-artifact-plugin/blob/maven-artifact-plugin-3.5.0/src/main/java/org/apache/maven/plugins/artifact/buildinfo/BuildInfoWriter.java#L140

But this is not a problem either since during release a non-snapshot
version is used.
This commit is contained in:
Marcono1234 2023-11-19 18:01:19 +01:00 committed by GitHub
parent 6684726476
commit 08174e2019
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 215 additions and 265 deletions

View File

@ -41,13 +41,13 @@ public class GsonProguardExampleActivity extends Activity {
Cart cart = buildCart(); Cart cart = buildCart();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Gson.toJson() example: \n"); sb.append("Gson.toJson() example: \n");
sb.append(" Cart Object: ").append(cart).append("\n"); sb.append(" Cart Object: ").append(cart).append('\n');
sb.append(" Cart JSON: ").append(gson.toJson(cart)).append("\n"); sb.append(" Cart JSON: ").append(gson.toJson(cart)).append('\n');
sb.append("\n\nGson.fromJson() example: \n"); sb.append("\n\nGson.fromJson() example: \n");
String json = "{buyer:'Happy Camper',creditCard:'4111-1111-1111-1111'," String json = "{buyer:'Happy Camper',creditCard:'4111-1111-1111-1111',"
+ "lineItems:[{name:'nails',priceInMicros:100000,quantity:100,currencyCode:'USD'}]}"; + "lineItems:[{name:'nails',priceInMicros:100000,quantity:100,currencyCode:'USD'}]}";
sb.append("Cart JSON: ").append(json).append("\n"); sb.append("Cart JSON: ").append(json).append('\n');
sb.append("Cart Object: ").append(gson.fromJson(json, Cart.class)).append("\n"); sb.append("Cart Object: ").append(gson.fromJson(json, Cart.class)).append('\n');
tv.setText(sb.toString()); tv.setText(sb.toString());
tv.invalidate(); tv.invalidate();
} }

View File

@ -216,9 +216,9 @@ public final class Gson {
* following settings: * following settings:
* *
* <ul> * <ul>
* <li>The JSON generated by <code>toJson</code> methods is in compact representation. This * <li>The JSON generated by {@code toJson} methods is in compact representation. This means
* means that all the unneeded white-space is removed. You can change this behavior with * that all the unneeded white-space is removed. You can change this behavior with {@link
* {@link GsonBuilder#setPrettyPrinting()}. * GsonBuilder#setPrettyPrinting()}.
* <li>When the JSON generated contains more than one line, the kind of newline and indent to * <li>When the JSON generated contains more than one line, the kind of newline and indent to
* use can be configured with {@link GsonBuilder#setFormattingStyle(FormattingStyle)}. * use can be configured with {@link GsonBuilder#setFormattingStyle(FormattingStyle)}.
* <li>The generated JSON omits all the fields that are null. Note that nulls in arrays are kept * <li>The generated JSON omits all the fields that are null. Note that nulls in arrays are kept
@ -240,13 +240,12 @@ public final class Gson {
* <li>By default, Gson ignores the {@link com.google.gson.annotations.Since} annotation. You * <li>By default, Gson ignores the {@link com.google.gson.annotations.Since} annotation. You
* can enable Gson to use this annotation through {@link GsonBuilder#setVersion(double)}. * can enable Gson to use this annotation through {@link GsonBuilder#setVersion(double)}.
* <li>The default field naming policy for the output JSON is same as in Java. So, a Java class * <li>The default field naming policy for the output JSON is same as in Java. So, a Java class
* field <code>versionNumber</code> will be output as <code>&quot;versionNumber&quot;</code> * field {@code versionNumber} will be output as {@code "versionNumber"} in JSON. The same
* in JSON. The same rules are applied for mapping incoming JSON to the Java classes. You * rules are applied for mapping incoming JSON to the Java classes. You can change this
* can change this policy through {@link * policy through {@link GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}.
* GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}. * <li>By default, Gson excludes {@code transient} or {@code static} fields from consideration
* <li>By default, Gson excludes <code>transient</code> or <code>static</code> fields from * for serialization and deserialization. You can change this behavior through {@link
* consideration for serialization and deserialization. You can change this behavior through * GsonBuilder#excludeFieldsWithModifiers(int...)}.
* {@link GsonBuilder#excludeFieldsWithModifiers(int...)}.
* <li>No explicit strictness is set. You can change this by calling {@link * <li>No explicit strictness is set. You can change this by calling {@link
* GsonBuilder#setStrictness(Strictness)}. * GsonBuilder#setStrictness(Strictness)}.
* </ul> * </ul>
@ -665,8 +664,8 @@ public final class Gson {
* is an example: * is an example:
* *
* <p>Let's say we want to write a type adapter that counts the number of objects being read from * <p>Let's say we want to write a type adapter that counts the number of objects being read from
* or written to JSON. We can achieve this by writing a type adapter factory that uses the <code> * or written to JSON. We can achieve this by writing a type adapter factory that uses the {@code
* getDelegateAdapter</code> method: * getDelegateAdapter} method:
* *
* <pre>{@code * <pre>{@code
* class StatsTypeAdapterFactory implements TypeAdapterFactory { * class StatsTypeAdapterFactory implements TypeAdapterFactory {

View File

@ -227,8 +227,8 @@ public final class GsonBuilder {
} }
/** /**
* Configure Gson to serialize null fields. By default, Gson omits all fields that are null during * Configures Gson to serialize null fields. By default, Gson omits all fields that are null
* serialization. * during serialization.
* *
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2 * @since 1.2
@ -240,10 +240,11 @@ public final class GsonBuilder {
} }
/** /**
* Enabling this feature will only change the serialized form if the map key is a complex type * Configures Gson to serialize {@code Map} objects with complex keys as JSON arrays. Enabling
* (i.e. non-primitive) in its <strong>serialized</strong> JSON form. The default implementation * this feature will only change the serialized form if the map key is a complex type (i.e.
* of map serialization uses {@code toString()} on the key; however, when this is called then one * non-primitive) in its <strong>serialized</strong> JSON form. The default implementation of map
* of the following cases apply: * serialization uses {@code toString()} on the key; however, when this is called then one of the
* following cases apply:
* *
* <p><b>Maps as JSON objects</b> * <p><b>Maps as JSON objects</b>
* *
@ -622,23 +623,24 @@ public final class GsonBuilder {
} }
/** /**
* Configures Gson to serialize {@code Date} objects according to the style value provided. You * Configures Gson to serialize {@code Date} objects according to the date style value provided.
* can call this method or {@link #setDateFormat(String)} multiple times, but only the last * You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format. * invocation will be used to decide the serialization format. This methods leaves the current
* 'time style' unchanged.
* *
* <p>Note that this style value should be one of the predefined constants in the {@code * <p>Note that this style value should be one of the predefined constants in the {@link
* DateFormat} class. See the documentation in {@link java.text.DateFormat} for more information * DateFormat} class, such as {@link DateFormat#MEDIUM}. See the documentation of the {@link
* on the valid style constants. * DateFormat} class for more information on the valid style constants.
* *
* @param style the predefined date style that date objects will be serialized/deserialized * @param dateStyle the predefined date style that date objects will be serialized/deserialized
* to/from * to/from
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @throws IllegalArgumentException if the style is invalid * @throws IllegalArgumentException if the style is invalid
* @since 1.2 * @since 1.2
*/ */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public GsonBuilder setDateFormat(int style) { public GsonBuilder setDateFormat(int dateStyle) {
this.dateStyle = checkDateFormatStyle(style); this.dateStyle = checkDateFormatStyle(dateStyle);
this.datePattern = null; this.datePattern = null;
return this; return this;
} }
@ -648,9 +650,9 @@ public final class GsonBuilder {
* can call this method or {@link #setDateFormat(String)} multiple times, but only the last * can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format. * invocation will be used to decide the serialization format.
* *
* <p>Note that this style value should be one of the predefined constants in the {@code * <p>Note that this style value should be one of the predefined constants in the {@link
* DateFormat} class. See the documentation in {@link java.text.DateFormat} for more information * DateFormat} class, such as {@link DateFormat#MEDIUM}. See the documentation of the {@link
* on the valid style constants. * DateFormat} class for more information on the valid style constants.
* *
* @param dateStyle the predefined date style that date objects will be serialized/deserialized * @param dateStyle the predefined date style that date objects will be serialized/deserialized
* to/from * to/from

View File

@ -117,6 +117,11 @@ public interface ReflectionAccessFilter {
? FilterResult.BLOCK_INACCESSIBLE ? FilterResult.BLOCK_INACCESSIBLE
: FilterResult.INDECISIVE; : FilterResult.INDECISIVE;
} }
@Override
public String toString() {
return "ReflectionAccessFilter#BLOCK_INACCESSIBLE_JAVA";
}
}; };
/** /**
@ -143,6 +148,11 @@ public interface ReflectionAccessFilter {
? FilterResult.BLOCK_ALL ? FilterResult.BLOCK_ALL
: FilterResult.INDECISIVE; : FilterResult.INDECISIVE;
} }
@Override
public String toString() {
return "ReflectionAccessFilter#BLOCK_ALL_JAVA";
}
}; };
/** /**
@ -169,6 +179,11 @@ public interface ReflectionAccessFilter {
? FilterResult.BLOCK_ALL ? FilterResult.BLOCK_ALL
: FilterResult.INDECISIVE; : FilterResult.INDECISIVE;
} }
@Override
public String toString() {
return "ReflectionAccessFilter#BLOCK_ALL_ANDROID";
}
}; };
/** /**
@ -196,6 +211,11 @@ public interface ReflectionAccessFilter {
? FilterResult.BLOCK_ALL ? FilterResult.BLOCK_ALL
: FilterResult.INDECISIVE; : FilterResult.INDECISIVE;
} }
@Override
public String toString() {
return "ReflectionAccessFilter#BLOCK_ALL_PLATFORM";
}
}; };
/** /**

View File

@ -68,11 +68,11 @@ import java.io.Writer;
* #write(JsonWriter,Object) write()} must write exactly one value. For primitive types this is * #write(JsonWriter,Object) write()} must write exactly one value. For primitive types this is
* means readers should make exactly one call to {@code nextBoolean()}, {@code nextDouble()}, {@code * means readers should make exactly one call to {@code nextBoolean()}, {@code nextDouble()}, {@code
* nextInt()}, {@code nextLong()}, {@code nextString()} or {@code nextNull()}. Writers should make * nextInt()}, {@code nextLong()}, {@code nextString()} or {@code nextNull()}. Writers should make
* exactly one call to one of <code>value()</code> or <code>nullValue()</code>. For arrays, type * exactly one call to one of {@code value()} or {@code nullValue()}. For arrays, type adapters
* adapters should start with a call to {@code beginArray()}, convert all elements, and finish with * should start with a call to {@code beginArray()}, convert all elements, and finish with a call to
* a call to {@code endArray()}. For objects, they should start with {@code beginObject()}, convert * {@code endArray()}. For objects, they should start with {@code beginObject()}, convert the
* the object, and finish with {@code endObject()}. Failing to convert a value or converting too * object, and finish with {@code endObject()}. Failing to convert a value or converting too many
* many values may cause the application to crash. * values may cause the application to crash.
* *
* <p>Type adapters should be prepared to read null from the stream and write it to the stream. * <p>Type adapters should be prepared to read null from the stream and write it to the stream.
* Alternatively, they should use {@link #nullSafe()} method while registering the type adapter with * Alternatively, they should use {@link #nullSafe()} method while registering the type adapter with

View File

@ -200,7 +200,7 @@ public class TypeToken<T> {
return rawType.isAssignableFrom($Gson$Types.getRawType(from)) return rawType.isAssignableFrom($Gson$Types.getRawType(from))
&& isAssignableFrom(from, (GenericArrayType) type); && isAssignableFrom(from, (GenericArrayType) type);
} else { } else {
throw buildUnexpectedTypeError( throw buildUnsupportedTypeException(
type, Class.class, ParameterizedType.class, GenericArrayType.class); type, Class.class, ParameterizedType.class, GenericArrayType.class);
} }
} }
@ -309,10 +309,11 @@ public class TypeToken<T> {
return false; return false;
} }
private static AssertionError buildUnexpectedTypeError(Type token, Class<?>... expected) { private static IllegalArgumentException buildUnsupportedTypeException(
Type token, Class<?>... expected) {
// Build exception message // Build exception message
StringBuilder exceptionMessage = new StringBuilder("Unexpected type. Expected one of: "); StringBuilder exceptionMessage = new StringBuilder("Unsupported type, expected one of: ");
for (Class<?> clazz : expected) { for (Class<?> clazz : expected) {
exceptionMessage.append(clazz.getName()).append(", "); exceptionMessage.append(clazz.getName()).append(", ");
} }
@ -320,10 +321,9 @@ public class TypeToken<T> {
.append("but got: ") .append("but got: ")
.append(token.getClass().getName()) .append(token.getClass().getName())
.append(", for type token: ") .append(", for type token: ")
.append(token.toString()) .append(token.toString());
.append('.');
return new AssertionError(exceptionMessage.toString()); return new IllegalArgumentException(exceptionMessage.toString());
} }
/** /**

View File

@ -1056,7 +1056,6 @@ public class JsonReader implements Closeable {
* consumes the closing quote, but does not include it in the returned string. * consumes the closing quote, but does not include it in the returned string.
* *
* @param quote either ' or ". * @param quote either ' or ".
* @throws NumberFormatException if any unicode escape sequences are malformed.
*/ */
private String nextQuotedValue(char quote) throws IOException { private String nextQuotedValue(char quote) throws IOException {
// Like nextNonWhitespace, this uses locals 'p' and 'l' to save inner-loop field access. // Like nextNonWhitespace, this uses locals 'p' and 'l' to save inner-loop field access.
@ -1527,7 +1526,7 @@ public class JsonReader implements Closeable {
} }
} }
private void checkLenient() throws IOException { private void checkLenient() throws MalformedJsonException {
if (strictness != Strictness.LENIENT) { if (strictness != Strictness.LENIENT) {
throw syntaxError( throw syntaxError(
"Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON"); "Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON");
@ -1655,7 +1654,7 @@ public class JsonReader implements Closeable {
* backslash. The backslash '\' should have already been read. This supports both Unicode escapes * backslash. The backslash '\' should have already been read. This supports both Unicode escapes
* "u000A" and two-character escapes "\n". * "u000A" and two-character escapes "\n".
* *
* @throws MalformedJsonException if any Unicode escape sequences are malformed. * @throws MalformedJsonException if the escape sequence is malformed
*/ */
@SuppressWarnings("fallthrough") @SuppressWarnings("fallthrough")
private char readEscapeCharacter() throws IOException { private char readEscapeCharacter() throws IOException {
@ -1725,10 +1724,10 @@ public class JsonReader implements Closeable {
} }
/** /**
* Throws a new IO exception with the given message and a context snippet with this reader's * Throws a new {@link MalformedJsonException} with the given message and information about the
* content. * current location.
*/ */
private IOException syntaxError(String message) throws IOException { private MalformedJsonException syntaxError(String message) throws MalformedJsonException {
throw new MalformedJsonException( throw new MalformedJsonException(
message + locationString() + "\nSee " + TroubleshootingGuide.createUrl("malformed-json")); message + locationString() + "\nSee " + TroubleshootingGuide.createUrl("malformed-json"));
} }

View File

@ -24,28 +24,25 @@ package com.google.gson.stream;
*/ */
final class JsonScope { final class JsonScope {
/** An array with no elements requires no separators or newlines before it is closed. */ /** An array with no elements requires no separator before the next element. */
static final int EMPTY_ARRAY = 1; static final int EMPTY_ARRAY = 1;
/** An array with at least one value requires a comma and newline before the next element. */ /** An array with at least one value requires a separator before the next element. */
static final int NONEMPTY_ARRAY = 2; static final int NONEMPTY_ARRAY = 2;
/** An object with no name/value pairs requires no separators or newlines before it is closed. */ /** An object with no name/value pairs requires no separator before the next element. */
static final int EMPTY_OBJECT = 3; static final int EMPTY_OBJECT = 3;
/** An object whose most recent element is a key. The next element must be a value. */ /** An object whose most recent element is a key. The next element must be a value. */
static final int DANGLING_NAME = 4; static final int DANGLING_NAME = 4;
/** /** An object with at least one name/value pair requires a separator before the next element. */
* An object with at least one name/value pair requires a comma and newline before the next
* element.
*/
static final int NONEMPTY_OBJECT = 5; static final int NONEMPTY_OBJECT = 5;
/** No object or array has been started. */ /** No top-level value has been started yet. */
static final int EMPTY_DOCUMENT = 6; static final int EMPTY_DOCUMENT = 6;
/** A document with at an array or object. */ /** A top-level value has already been started. */
static final int NONEMPTY_DOCUMENT = 7; static final int NONEMPTY_DOCUMENT = 7;
/** A document that's been closed and cannot be accessed. */ /** A document that's been closed and cannot be accessed. */

View File

@ -356,9 +356,9 @@ public class JsonWriter implements Closeable, Flushable {
/** /**
* Configures this writer to emit JSON that's safe for direct inclusion in HTML and XML documents. * Configures this writer to emit JSON that's safe for direct inclusion in HTML and XML documents.
* This escapes the HTML characters {@code <}, {@code >}, {@code &} and {@code =} before writing * This escapes the HTML characters {@code <}, {@code >}, {@code &}, {@code =} and {@code '}
* them to the stream. Without this setting, your XML/HTML encoder should replace these characters * before writing them to the stream. Without this setting, your XML/HTML encoder should replace
* with the corresponding escape sequences. * these characters with the corresponding escape sequences.
*/ */
public final void setHtmlSafe(boolean htmlSafe) { public final void setHtmlSafe(boolean htmlSafe) {
this.htmlSafe = htmlSafe; this.htmlSafe = htmlSafe;

View File

@ -297,7 +297,7 @@ public class JsonPrimitiveTest {
new JsonPrimitive(new BigInteger("0")), new JsonPrimitive(0)); new JsonPrimitive(new BigInteger("0")), new JsonPrimitive(0));
MoreAsserts.assertEqualsAndHashCode(new JsonPrimitive(0), new JsonPrimitive(0L)); MoreAsserts.assertEqualsAndHashCode(new JsonPrimitive(0), new JsonPrimitive(0L));
MoreAsserts.assertEqualsAndHashCode( MoreAsserts.assertEqualsAndHashCode(
new JsonPrimitive(new BigInteger("0")), new JsonPrimitive(0)); new JsonPrimitive(new BigDecimal("0")), new JsonPrimitive(0));
MoreAsserts.assertEqualsAndHashCode( MoreAsserts.assertEqualsAndHashCode(
new JsonPrimitive(Float.NaN), new JsonPrimitive(Double.NaN)); new JsonPrimitive(Float.NaN), new JsonPrimitive(Double.NaN));
} }

View File

@ -74,11 +74,9 @@ public final class MixedStreamTest {
JsonReader jsonReader = new JsonReader(stringReader); JsonReader jsonReader = new JsonReader(stringReader);
jsonReader.beginArray(); jsonReader.beginArray();
// actual and expected object are inverted in the test. assertThat(gson.<Car>fromJson(jsonReader, Car.class)).isEqualTo(BLUE_MUSTANG);
// gson.fromJson(jsonReader, Car.class) as arg of assertThat() cause an ambiguous method call assertThat(gson.<Car>fromJson(jsonReader, Car.class)).isEqualTo(BLACK_BMW);
assertThat(BLUE_MUSTANG).isEqualTo(gson.fromJson(jsonReader, Car.class)); assertThat(gson.<Car>fromJson(jsonReader, Car.class)).isEqualTo(RED_MIATA);
assertThat(BLACK_BMW).isEqualTo(gson.fromJson(jsonReader, Car.class));
assertThat(RED_MIATA).isEqualTo(gson.fromJson(jsonReader, Car.class));
jsonReader.endArray(); jsonReader.endArray();
} }

View File

@ -1,42 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* 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.gson;
/**
* This is a configurable {@link ExclusionStrategy} that can be used for unit testing.
*
* @author Joel Leitch
*/
final class MockExclusionStrategy implements ExclusionStrategy {
private final boolean skipClass;
private final boolean skipField;
public MockExclusionStrategy(boolean skipClass, boolean skipField) {
this.skipClass = skipClass;
this.skipField = skipField;
}
@Override
public boolean shouldSkipField(FieldAttributes f) {
return skipField;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return skipClass;
}
}

View File

@ -24,6 +24,8 @@ import java.lang.reflect.Method;
/** /**
* Handles type conversion from some object to some primitive (or primitive wrapper instance). * Handles type conversion from some object to some primitive (or primitive wrapper instance).
* *
* <p>Used by {@link ParameterizedTypeFixtures.MyParameterizedTypeAdapter}.
*
* @author Joel Leitch * @author Joel Leitch
*/ */
final class PrimitiveTypeAdapter { final class PrimitiveTypeAdapter {

View File

@ -237,8 +237,8 @@ public class CollectionTest {
target.add(objB); target.add(objB);
String result = gson.toJson(target); String result = gson.toJson(target);
assertThat(result.startsWith("[")).isTrue(); assertThat(result).startsWith("[");
assertThat(result.endsWith("]")).isTrue(); assertThat(result).endsWith("]");
for (BagOfPrimitives obj : target) { for (BagOfPrimitives obj : target) {
assertThat(result).contains(obj.getExpectedJson()); assertThat(result).contains(obj.getExpectedJson());
} }
@ -290,10 +290,8 @@ public class CollectionTest {
for (Object bag1 : target) { for (Object bag1 : target) {
// Gson 2.0 converts raw objects into maps // Gson 2.0 converts raw objects into maps
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> values = (Map<String, Object>) bag1; Map<String, Object> map = (Map<String, Object>) bag1;
assertThat(values.containsValue(10.0)).isTrue(); assertThat(map.values()).containsExactly(10.0, 20.0, false, "stringValue");
assertThat(values.containsValue(20.0)).isTrue();
assertThat(values.containsValue("stringValue")).isTrue();
} }
} }

View File

@ -82,7 +82,7 @@ public class EscapingTest {
BagOfPrimitives target = new BagOfPrimitives(1L, 1, true, "test' / w'ith\" / \\ <script>"); BagOfPrimitives target = new BagOfPrimitives(1L, 1, true, "test' / w'ith\" / \\ <script>");
String escapedJsonForm = escapeHtmlGson.toJson(target); String escapedJsonForm = escapeHtmlGson.toJson(target);
String nonEscapedJsonForm = noEscapeHtmlGson.toJson(target); String nonEscapedJsonForm = noEscapeHtmlGson.toJson(target);
assertThat(escapedJsonForm.equals(nonEscapedJsonForm)).isFalse(); assertThat(escapedJsonForm).isNotEqualTo(nonEscapedJsonForm);
assertThat(noEscapeHtmlGson.fromJson(escapedJsonForm, BagOfPrimitives.class)).isEqualTo(target); assertThat(noEscapeHtmlGson.fromJson(escapedJsonForm, BagOfPrimitives.class)).isEqualTo(target);
assertThat(escapeHtmlGson.fromJson(nonEscapedJsonForm, BagOfPrimitives.class)) assertThat(escapeHtmlGson.fromJson(nonEscapedJsonForm, BagOfPrimitives.class))

View File

@ -74,10 +74,10 @@ public class InstanceCreatorTest {
String json = "{baseName:'Base',subName:'SubRevised'}"; String json = "{baseName:'Base',subName:'SubRevised'}";
Base base = gson.fromJson(json, Base.class); Base base = gson.fromJson(json, Base.class);
assertThat(base instanceof Sub).isTrue(); assertThat(base).isInstanceOf(Sub.class);
Sub sub = (Sub) base; Sub sub = (Sub) base;
assertThat("SubRevised".equals(sub.subName)).isFalse(); assertThat(sub.subName).isNotEqualTo("SubRevised");
assertThat(sub.subName).isEqualTo(Sub.SUB_NAME); assertThat(sub.subName).isEqualTo(Sub.SUB_NAME);
} }
@ -96,7 +96,7 @@ public class InstanceCreatorTest {
.create(); .create();
String json = "{base:{baseName:'Base',subName:'SubRevised'}}"; String json = "{base:{baseName:'Base',subName:'SubRevised'}}";
ClassWithBaseField target = gson.fromJson(json, ClassWithBaseField.class); ClassWithBaseField target = gson.fromJson(json, ClassWithBaseField.class);
assertThat(target.base instanceof Sub).isTrue(); assertThat(target.base).isInstanceOf(Sub.class);
assertThat(((Sub) target.base).subName).isEqualTo(Sub.SUB_NAME); assertThat(((Sub) target.base).subName).isEqualTo(Sub.SUB_NAME);
} }

View File

@ -134,11 +134,11 @@ public class JsonParserTest {
@Test @Test
public void testExtraCommasInArrays() { public void testExtraCommasInArrays() {
Type type = new TypeToken<List<String>>() {}.getType(); TypeToken<List<String>> type = new TypeToken<>() {};
assertThat(Arrays.asList("a", null, "b", null, null)) assertThat(gson.fromJson("[a,,b,,]", type))
.isEqualTo(gson.fromJson("[a,,b,,]", type)); .isEqualTo(Arrays.asList("a", null, "b", null, null));
assertThat(Arrays.asList(null, null)).isEqualTo(gson.fromJson("[,]", type)); assertThat(gson.fromJson("[,]", type)).isEqualTo(Arrays.asList(null, null));
assertThat(Arrays.asList("a", null)).isEqualTo(gson.fromJson("[a,]", type)); assertThat(gson.fromJson("[a,]", type)).isEqualTo(Arrays.asList("a", null));
} }
@Test @Test

View File

@ -589,8 +589,7 @@ public class MapTest {
Map<String, String> map = new LinkedHashMap<>(); Map<String, String> map = new LinkedHashMap<>();
map.put("2,3", "a"); map.put("2,3", "a");
map.put("5,7", "b"); map.put("5,7", "b");
assertThat(map) assertThat(gson.fromJson(json, new TypeToken<Map<String, String>>() {})).isEqualTo(map);
.isEqualTo(gson.fromJson(json, new TypeToken<Map<String, String>>() {}.getType()));
} }
@Test @Test
@ -599,8 +598,7 @@ public class MapTest {
Map<Double, String> map = new LinkedHashMap<>(); Map<Double, String> map = new LinkedHashMap<>();
map.put(2.3, "a"); map.put(2.3, "a");
map.put(5.7, "b"); map.put(5.7, "b");
assertThat(map) assertThat(gson.fromJson(json, new TypeToken<Map<Double, String>>() {})).isEqualTo(map);
.isEqualTo(gson.fromJson(json, new TypeToken<Map<Double, String>>() {}.getType()));
} }
@Test @Test
@ -609,8 +607,7 @@ public class MapTest {
Map<Boolean, String> map = new LinkedHashMap<>(); Map<Boolean, String> map = new LinkedHashMap<>();
map.put(true, "a"); map.put(true, "a");
map.put(false, "b"); map.put(false, "b");
assertThat(map) assertThat(gson.fromJson(json, new TypeToken<Map<Boolean, String>>() {})).isEqualTo(map);
.isEqualTo(gson.fromJson(json, new TypeToken<Map<Boolean, String>>() {}.getType()));
} }
@Test @Test
@ -634,14 +631,14 @@ public class MapTest {
} }
@Test @Test
public void testDeerializeMapOfMaps() { public void testDeserializeMapOfMaps() {
Type type = new TypeToken<Map<String, Map<String, String>>>() {}.getType(); TypeToken<Map<String, Map<String, String>>> type = new TypeToken<>() {};
Map<String, Map<String, String>> map = Map<String, Map<String, String>> map =
newMap( newMap(
"a", newMap("ka1", "va1", "ka2", "va2"), "a", newMap("ka1", "va1", "ka2", "va2"),
"b", newMap("kb1", "vb1", "kb2", "vb2")); "b", newMap("kb1", "vb1", "kb2", "vb2"));
String json = "{'a':{'ka1':'va1','ka2':'va2'},'b':{'kb1':'vb1','kb2':'vb2'}}"; String json = "{'a':{'ka1':'va1','ka2':'va2'},'b':{'kb1':'vb1','kb2':'vb2'}}";
assertThat(map).isEqualTo(gson.fromJson(json, type)); assertThat(gson.fromJson(json, type)).isEqualTo(map);
} }
private <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) { private <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
@ -657,8 +654,7 @@ public class MapTest {
Map<Double, String> map = new LinkedHashMap<>(); Map<Double, String> map = new LinkedHashMap<>();
map.put(2.3, "a"); map.put(2.3, "a");
JsonElement tree = JsonParser.parseString(json); JsonElement tree = JsonParser.parseString(json);
assertThat(map) assertThat(gson.fromJson(tree, new TypeToken<Map<Double, String>>() {})).isEqualTo(map);
.isEqualTo(gson.fromJson(tree, new TypeToken<Map<Double, String>>() {}.getType()));
} }
static class Point { static class Point {

View File

@ -243,7 +243,7 @@ public class NullObjectAndFieldTest {
} }
@Test @Test
public void testCustomTypeAdapterPassesNullDesrialization() { public void testCustomTypeAdapterPassesNullDeserialization() {
Gson gson = Gson gson =
new GsonBuilder() new GsonBuilder()
.registerTypeAdapter( .registerTypeAdapter(

View File

@ -39,7 +39,8 @@ public class NumberLimitsTest {
* large or small numbers (it rounds to 0 or Infinity) (to be verified?; if it had * large or small numbers (it rounds to 0 or Infinity) (to be verified?; if it had
* performance problems with certain numbers, then it would affect other parts of Gson which * performance problems with certain numbers, then it would affect other parts of Gson which
* parse as float or double as well) * parse as float or double as well)
* <li>Enforcing limits only when a JSON number is encountered would be ineffective unless users * <li>Enforcing limits only when a JSON number is encountered would be ineffective when users
* want to consume a JSON number as string using {@link JsonReader#nextString()} unless they
* explicitly call {@link JsonReader#peek()} and check if the value is a JSON number. * explicitly call {@link JsonReader#peek()} and check if the value is a JSON number.
* Otherwise the limits could be circumvented because {@link JsonReader#nextString()} reads * Otherwise the limits could be circumvented because {@link JsonReader#nextString()} reads
* both strings and numbers, and for JSON strings no restrictions are enforced. * both strings and numbers, and for JSON strings no restrictions are enforced.

View File

@ -141,9 +141,9 @@ public class ObjectTest {
@Test @Test
public void testClassWithTransientFieldsDeserializationTransientFieldsPassedInJsonAreIgnored() { public void testClassWithTransientFieldsDeserializationTransientFieldsPassedInJsonAreIgnored() {
String json = "{\"transientLongValue\":1,\"longValue\":[1]}"; String json = "{\"transientLongValue\":5,\"longValue\":[1]}";
ClassWithTransientFields<?> target = gson.fromJson(json, ClassWithTransientFields.class); ClassWithTransientFields<?> target = gson.fromJson(json, ClassWithTransientFields.class);
assertThat(target.transientLongValue != 1).isFalse(); assertThat(target.transientLongValue).isEqualTo(1);
} }
@Test @Test

View File

@ -555,8 +555,8 @@ public class PrimitiveTest {
@Test @Test
public void testDoubleNaNDeserialization() { public void testDoubleNaNDeserialization() {
assertThat(Double.isNaN(gson.fromJson("NaN", Double.class))).isTrue(); assertThat(gson.fromJson("NaN", Double.class)).isNaN();
assertThat(Double.isNaN(gson.fromJson("NaN", double.class))).isTrue(); assertThat(gson.fromJson("NaN", double.class)).isNaN();
} }
@Test @Test
@ -584,8 +584,8 @@ public class PrimitiveTest {
@Test @Test
public void testFloatNaNDeserialization() { public void testFloatNaNDeserialization() {
assertThat(Float.isNaN(gson.fromJson("NaN", Float.class))).isTrue(); assertThat(gson.fromJson("NaN", Float.class)).isNaN();
assertThat(Float.isNaN(gson.fromJson("NaN", float.class))).isTrue(); assertThat(gson.fromJson("NaN", float.class)).isNaN();
} }
@Test @Test
@ -622,8 +622,8 @@ public class PrimitiveTest {
@Test @Test
public void testDoubleInfinityDeserialization() { public void testDoubleInfinityDeserialization() {
assertThat(Double.isInfinite(gson.fromJson("Infinity", Double.class))).isTrue(); assertThat(gson.fromJson("Infinity", Double.class)).isPositiveInfinity();
assertThat(Double.isInfinite(gson.fromJson("Infinity", double.class))).isTrue(); assertThat(gson.fromJson("Infinity", double.class)).isPositiveInfinity();
} }
@Test @Test
@ -651,8 +651,8 @@ public class PrimitiveTest {
@Test @Test
public void testFloatInfinityDeserialization() { public void testFloatInfinityDeserialization() {
assertThat(Float.isInfinite(gson.fromJson("Infinity", Float.class))).isTrue(); assertThat(gson.fromJson("Infinity", Float.class)).isPositiveInfinity();
assertThat(Float.isInfinite(gson.fromJson("Infinity", float.class))).isTrue(); assertThat(gson.fromJson("Infinity", float.class)).isPositiveInfinity();
} }
@Test @Test
@ -689,8 +689,8 @@ public class PrimitiveTest {
@Test @Test
public void testNegativeInfinityDeserialization() { public void testNegativeInfinityDeserialization() {
assertThat(Double.isInfinite(gson.fromJson("-Infinity", double.class))).isTrue(); assertThat(gson.fromJson("-Infinity", double.class)).isNegativeInfinity();
assertThat(Double.isInfinite(gson.fromJson("-Infinity", Double.class))).isTrue(); assertThat(gson.fromJson("-Infinity", Double.class)).isNegativeInfinity();
} }
@Test @Test
@ -718,8 +718,8 @@ public class PrimitiveTest {
@Test @Test
public void testNegativeInfinityFloatDeserialization() { public void testNegativeInfinityFloatDeserialization() {
assertThat(Float.isInfinite(gson.fromJson("-Infinity", float.class))).isTrue(); assertThat(gson.fromJson("-Infinity", float.class)).isNegativeInfinity();
assertThat(Float.isInfinite(gson.fromJson("-Infinity", Float.class))).isTrue(); assertThat(gson.fromJson("-Infinity", Float.class)).isNegativeInfinity();
} }
@Test @Test

View File

@ -192,7 +192,7 @@ public class ReadersWritersTest {
gson.toJson(Arrays.asList("test", 123, true), appendable); gson.toJson(Arrays.asList("test", 123, true), appendable);
// Make sure CharSequence.toString() was called at least two times to verify that // Make sure CharSequence.toString() was called at least two times to verify that
// CurrentWrite.cachedString is properly overwritten when char array changes // CurrentWrite.cachedString is properly overwritten when char array changes
assertThat(appendable.toStringCallCount >= 2).isTrue(); assertThat(appendable.toStringCallCount).isAtLeast(2);
assertThat(appendable.stringBuilder.toString()).isEqualTo("[\"test\",123,true]"); assertThat(appendable.stringBuilder.toString()).isEqualTo("[\"test\",123,true]");
} }
} }

View File

@ -38,7 +38,9 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.junit.Test; import org.junit.Test;
@ -514,4 +516,27 @@ public class ReflectionAccessFilterTest {
+ " this type. Interface name: java.lang.Runnable"); + " this type. Interface name: java.lang.Runnable");
} }
} }
/**
* Verifies that the predefined filter constants have meaningful {@code toString()} output to make
* debugging easier.
*/
@Test
public void testConstantsToString() throws Exception {
List<Field> constantFields = new ArrayList<>();
for (Field f : ReflectionAccessFilter.class.getFields()) {
// Only include ReflectionAccessFilter constants (in case any other fields are added in the
// future)
if (f.getType() == ReflectionAccessFilter.class) {
constantFields.add(f);
}
}
assertThat(constantFields).isNotEmpty();
for (Field f : constantFields) {
Object constant = f.get(null);
assertThat(constant.toString()).isEqualTo("ReflectionAccessFilter#" + f.getName());
}
}
} }

View File

@ -114,8 +114,8 @@ public final class RuntimeTypeAdapterFactoryFunctionalTest {
} }
/** /**
* Creates a new runtime type adapter using for {@code baseType} using {@code typeFieldName} as * Creates a new runtime type adapter for {@code baseType} using {@code typeFieldName} as the
* the type field name. Type field names are case sensitive. * type field name. Type field names are case sensitive.
*/ */
public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName) { public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName) {
return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName); return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName);

View File

@ -44,7 +44,7 @@ public class SecurityTest {
public void testNonExecutableJsonSerialization() { public void testNonExecutableJsonSerialization() {
Gson gson = gsonBuilder.generateNonExecutableJson().create(); Gson gson = gsonBuilder.generateNonExecutableJson().create();
String json = gson.toJson(new BagOfPrimitives()); String json = gson.toJson(new BagOfPrimitives());
assertThat(json.startsWith(JSON_NON_EXECUTABLE_PREFIX)).isTrue(); assertThat(json).startsWith(JSON_NON_EXECUTABLE_PREFIX);
} }
@Test @Test

View File

@ -83,7 +83,7 @@ public final class GsonTypesTest {
private final class NonStaticInner<T> {} private final class NonStaticInner<T> {}
/** /**
* Given a parameterized type A&lt;B,C&gt;, returns B. If the specified type is not a generic * Given a parameterized type {@code A<B, C>}, returns B. If the specified type is not a generic
* type, returns null. * type, returns null.
*/ */
public static Type getFirstTypeArgument(Type type) throws Exception { public static Type getFirstTypeArgument(Type type) throws Exception {

View File

@ -31,7 +31,7 @@ public class JavaVersionTest {
@Test @Test
public void testGetMajorJavaVersion() { public void testGetMajorJavaVersion() {
// Gson currently requires at least Java 7 // Gson currently requires at least Java 7
assertThat(JavaVersion.getMajorJavaVersion() >= 7).isTrue(); assertThat(JavaVersion.getMajorJavaVersion()).isAtLeast(7);
} }
@Test @Test

View File

@ -48,7 +48,7 @@ public final class JsonElementReaderTest {
JsonTreeReader reader = new JsonTreeReader(element); JsonTreeReader reader = new JsonTreeReader(element);
reader.setStrictness(Strictness.LENIENT); reader.setStrictness(Strictness.LENIENT);
reader.beginArray(); reader.beginArray();
assertThat(Double.isNaN(reader.nextDouble())).isTrue(); assertThat(reader.nextDouble()).isNaN();
assertThat(reader.nextDouble()).isEqualTo(Double.NEGATIVE_INFINITY); assertThat(reader.nextDouble()).isEqualTo(Double.NEGATIVE_INFINITY);
assertThat(reader.nextDouble()).isEqualTo(Double.POSITIVE_INFINITY); assertThat(reader.nextDouble()).isEqualTo(Double.POSITIVE_INFINITY);
reader.endArray(); reader.endArray();

View File

@ -28,7 +28,6 @@ import java.util.GregorianCalendar;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import org.junit.Test; import org.junit.Test;
import org.junit.function.ThrowingRunnable;
public class ISO8601UtilsTest { public class ISO8601UtilsTest {
@ -130,13 +129,6 @@ public class ISO8601UtilsTest {
@Test @Test
public void testDateParseInvalidTime() { public void testDateParseInvalidTime() {
final String dateStr = "2018-06-25T61:60:62-03:00"; final String dateStr = "2018-06-25T61:60:62-03:00";
assertThrows( assertThrows(ParseException.class, () -> ISO8601Utils.parse(dateStr, new ParsePosition(0)));
ParseException.class,
new ThrowingRunnable() {
@Override
public void run() throws Throwable {
ISO8601Utils.parse(dateStr, new ParsePosition(0));
}
});
} }
} }

View File

@ -54,7 +54,7 @@ public class Java17ReflectionHelperTest {
.newInstance(new PrincipalImpl("user"), new PrincipalImpl("group")); .newInstance(new PrincipalImpl("user"), new PrincipalImpl("group"));
String[] componentNames = ReflectionHelper.getRecordComponentNames(unixDomainPrincipalClass); String[] componentNames = ReflectionHelper.getRecordComponentNames(unixDomainPrincipalClass);
assertThat(componentNames.length > 0).isTrue(); assertThat(componentNames).isNotEmpty();
for (String componentName : componentNames) { for (String componentName : componentNames) {
Field componentField = unixDomainPrincipalClass.getDeclaredField(componentName); Field componentField = unixDomainPrincipalClass.getDeclaredField(componentName);

View File

@ -24,6 +24,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable; import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -81,6 +82,18 @@ public final class TypeTokenTest {
listOfUnknown = listOfString; // compiles; must be true listOfUnknown = listOfString; // compiles; must be true
// The following assertion is too difficult to support reliably, so disabling // The following assertion is too difficult to support reliably, so disabling
// assertThat(TypeToken.get(b).isAssignableFrom(a)).isTrue(); // assertThat(TypeToken.get(b).isAssignableFrom(a)).isTrue();
WildcardType wildcardType = (WildcardType) ((ParameterizedType) b).getActualTypeArguments()[0];
TypeToken<?> wildcardTypeToken = TypeToken.get(wildcardType);
IllegalArgumentException e =
assertThrows(IllegalArgumentException.class, () -> wildcardTypeToken.isAssignableFrom(b));
assertThat(e)
.hasMessageThat()
.isEqualTo(
"Unsupported type, expected one of: java.lang.Class,"
+ " java.lang.reflect.ParameterizedType, java.lang.reflect.GenericArrayType, but"
+ " got: com.google.gson.internal.$Gson$Types$WildcardTypeImpl, for type token: "
+ wildcardTypeToken);
} }
@SuppressWarnings({"deprecation"}) @SuppressWarnings({"deprecation"})

View File

@ -714,7 +714,7 @@ public final class JsonReaderTest {
JsonReader reader = new JsonReader(reader(json)); JsonReader reader = new JsonReader(reader(json));
reader.setStrictness(Strictness.LENIENT); reader.setStrictness(Strictness.LENIENT);
reader.beginArray(); reader.beginArray();
assertThat(Double.isNaN(reader.nextDouble())).isTrue(); assertThat(reader.nextDouble()).isNaN();
assertThat(reader.nextDouble()).isEqualTo(Double.NEGATIVE_INFINITY); assertThat(reader.nextDouble()).isEqualTo(Double.NEGATIVE_INFINITY);
assertThat(reader.nextDouble()).isEqualTo(Double.POSITIVE_INFINITY); assertThat(reader.nextDouble()).isEqualTo(Double.POSITIVE_INFINITY);
reader.endArray(); reader.endArray();
@ -726,7 +726,7 @@ public final class JsonReaderTest {
JsonReader reader = new JsonReader(reader(json)); JsonReader reader = new JsonReader(reader(json));
reader.setStrictness(Strictness.LENIENT); reader.setStrictness(Strictness.LENIENT);
reader.beginArray(); reader.beginArray();
assertThat(Double.isNaN(reader.nextDouble())).isTrue(); assertThat(reader.nextDouble()).isNaN();
assertThat(reader.nextDouble()).isEqualTo(Double.NEGATIVE_INFINITY); assertThat(reader.nextDouble()).isEqualTo(Double.NEGATIVE_INFINITY);
assertThat(reader.nextDouble()).isEqualTo(Double.POSITIVE_INFINITY); assertThat(reader.nextDouble()).isEqualTo(Double.POSITIVE_INFINITY);
reader.endArray(); reader.endArray();

View File

@ -286,10 +286,7 @@ public final class JsonWriterTest {
assertThat(stringWriter.toString()).isEqualTo("{\"a\":{\"b\":true},\"c\":1}"); assertThat(stringWriter.toString()).isEqualTo("{\"a\":{\"b\":true},\"c\":1}");
} }
@Test private static void assertNonFiniteFloatsExceptions(JsonWriter jsonWriter) throws IOException {
public void testNonFiniteFloats() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.beginArray(); jsonWriter.beginArray();
IllegalArgumentException expected = IllegalArgumentException expected =
@ -311,27 +308,38 @@ public final class JsonWriterTest {
.isEqualTo("Numeric values must be finite, but was Infinity"); .isEqualTo("Numeric values must be finite, but was Infinity");
} }
@Test
public void testNonFiniteFloats() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
assertNonFiniteFloatsExceptions(jsonWriter);
}
@Test @Test
public void testNonFiniteFloatsWhenStrict() throws IOException { public void testNonFiniteFloatsWhenStrict() throws IOException {
StringWriter stringWriter = new StringWriter(); StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter); JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.setStrictness(Strictness.STRICT); jsonWriter.setStrictness(Strictness.STRICT);
assertNonFiniteFloatsExceptions(jsonWriter);
}
private static void assertNonFiniteDoublesExceptions(JsonWriter jsonWriter) throws IOException {
jsonWriter.beginArray(); jsonWriter.beginArray();
IllegalArgumentException expected = IllegalArgumentException expected =
assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Float.NaN)); assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Double.NaN));
assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN"); assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN");
expected = expected =
assertThrows( assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Float.NEGATIVE_INFINITY)); IllegalArgumentException.class, () -> jsonWriter.value(Double.NEGATIVE_INFINITY));
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.isEqualTo("Numeric values must be finite, but was -Infinity"); .isEqualTo("Numeric values must be finite, but was -Infinity");
expected = expected =
assertThrows( assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Float.POSITIVE_INFINITY)); IllegalArgumentException.class, () -> jsonWriter.value(Double.POSITIVE_INFINITY));
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity"); .isEqualTo("Numeric values must be finite, but was Infinity");
@ -341,25 +349,7 @@ public final class JsonWriterTest {
public void testNonFiniteDoubles() throws IOException { public void testNonFiniteDoubles() throws IOException {
StringWriter stringWriter = new StringWriter(); StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter); JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.beginArray(); assertNonFiniteDoublesExceptions(jsonWriter);
IllegalArgumentException expected =
assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Double.NaN));
assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN");
expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.NEGATIVE_INFINITY));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was -Infinity");
expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.POSITIVE_INFINITY));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
} }
@Test @Test
@ -367,22 +357,37 @@ public final class JsonWriterTest {
StringWriter stringWriter = new StringWriter(); StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter); JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.setStrictness(Strictness.STRICT); jsonWriter.setStrictness(Strictness.STRICT);
assertNonFiniteDoublesExceptions(jsonWriter);
}
private static void assertNonFiniteNumbersExceptions(JsonWriter jsonWriter) throws IOException {
jsonWriter.beginArray(); jsonWriter.beginArray();
IllegalArgumentException expected = IllegalArgumentException expected =
assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Double.NaN)); assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.valueOf(Double.NaN)));
assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN"); assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN");
expected = expected =
assertThrows( assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.NEGATIVE_INFINITY)); IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.NEGATIVE_INFINITY)));
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.isEqualTo("Numeric values must be finite, but was -Infinity"); .isEqualTo("Numeric values must be finite, but was -Infinity");
expected = expected =
assertThrows( assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.POSITIVE_INFINITY)); IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.POSITIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(new LazilyParsedNumber("Infinity")));
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity"); .isEqualTo("Numeric values must be finite, but was Infinity");
@ -392,36 +397,7 @@ public final class JsonWriterTest {
public void testNonFiniteNumbers() throws IOException { public void testNonFiniteNumbers() throws IOException {
StringWriter stringWriter = new StringWriter(); StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter); JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.beginArray(); assertNonFiniteNumbersExceptions(jsonWriter);
IllegalArgumentException expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.valueOf(Double.NaN)));
assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.NEGATIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was -Infinity");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.POSITIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(new LazilyParsedNumber("Infinity")));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
} }
@Test @Test
@ -429,36 +405,7 @@ public final class JsonWriterTest {
StringWriter stringWriter = new StringWriter(); StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter); JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.setStrictness(Strictness.STRICT); jsonWriter.setStrictness(Strictness.STRICT);
jsonWriter.beginArray(); assertNonFiniteNumbersExceptions(jsonWriter);
IllegalArgumentException expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.valueOf(Double.NaN)));
assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.NEGATIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was -Infinity");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.POSITIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(new LazilyParsedNumber("Infinity")));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
} }
@Test @Test

View File

@ -392,13 +392,13 @@ public final class ParseBenchmark {
StringBuilder result = StringBuilder result =
new StringBuilder() new StringBuilder()
.append(id) .append(id)
.append("\n") .append('\n')
.append(title) .append(title)
.append("\n") .append('\n')
.append(description) .append(description)
.append("\n") .append('\n')
.append(alternates) .append(alternates)
.append("\n") .append('\n')
.append(updated); .append(updated);
int i = 1; int i = 1;
for (Item item : items) { for (Item item : items) {

View File

@ -196,6 +196,9 @@
<executions> <executions>
<execution> <execution>
<goals> <goals>
<!-- This logs a warning about `source.scm.tag=HEAD`, but this can be ignored;
during release Maven Release Plugin temporarily changes the `source.scm.tag`
value to the actual Git tag, which will then not cause a warning -->
<goal>buildinfo</goal> <goal>buildinfo</goal>
</goals> </goals>
</execution> </execution>