Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify that JsonTreeReader and JsonTreeWriter override all methods #2181

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
57 changes: 55 additions & 2 deletions gson/src/test/java/com/google/gson/common/MoreAsserts.java
Expand Up @@ -16,9 +16,13 @@

package com.google.gson.common;

import org.junit.Assert;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.junit.Assert;

/**
* Handy asserts that we wish were present in {@link Assert}
Expand Down Expand Up @@ -49,4 +53,53 @@ public static void assertEqualsAndHashCode(Object a, Object b) {
Assert.assertFalse(a.equals(null));
Assert.assertFalse(a.equals(new Object()));
}

private static boolean isProtectedOrPublic(Method method) {
int modifiers = method.getModifiers();
return Modifier.isProtected(modifiers) || Modifier.isPublic(modifiers);
}

private static String getMethodSignature(Method method) {
StringBuilder builder = new StringBuilder(method.getName());
builder.append('(');

String sep = "";
for (Class<?> paramType : method.getParameterTypes()) {
builder.append(sep).append(paramType.getName());
sep = ",";
}

builder.append(')');
return builder.toString();
}

/**
* Asserts that {@code subClass} overrides all protected and public methods declared by
* {@code baseClass} except for the ones whose signatures are in {@code ignoredMethods}.
*/
public static void assertOverridesMethods(Class<?> baseClass, Class<?> subClass, List<String> ignoredMethods) {
Set<String> requiredOverriddenMethods = new LinkedHashSet<>();
for (Method method : baseClass.getDeclaredMethods()) {
// Note: Do not filter out `final` methods; maybe they should not be `final` and subclass needs
// to override them
if (isProtectedOrPublic(method)) {
requiredOverriddenMethods.add(getMethodSignature(method));
}
}

for (Method method : subClass.getDeclaredMethods()) {
requiredOverriddenMethods.remove(getMethodSignature(method));
}

for (String ignoredMethod : ignoredMethods) {
boolean foundIgnored = requiredOverriddenMethods.remove(ignoredMethod);
if (!foundIgnored) {
throw new IllegalArgumentException("Method '" + ignoredMethod + "' does not exist or is already overridden");
}
}

if (!requiredOverriddenMethods.isEmpty()) {
Assert.fail(subClass.getSimpleName() + " must override these methods: " + requiredOverriddenMethods);
}
}
}
Expand Up @@ -19,9 +19,14 @@
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.common.MoreAsserts;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.MalformedJsonException;
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import java.util.List;
import junit.framework.TestCase;

@SuppressWarnings("resource")
Expand Down Expand Up @@ -80,4 +85,14 @@ public JsonElement deepCopy() {
expected.getMessage());
}
}

/**
* {@link JsonTreeReader} effectively replaces the complete reading logic of {@link JsonReader} to
* read from a {@link JsonElement} instead of a {@link Reader}. Therefore all relevant methods of
* {@code JsonReader} must be overridden.
*/
public void testOverrides() {
List<String> ignoredMethods = Arrays.asList("setLenient(boolean)", "isLenient()");
MoreAsserts.assertOverridesMethods(JsonReader.class, JsonTreeReader.class, ignoredMethods);
}
}
Expand Up @@ -16,8 +16,14 @@

package com.google.gson.internal.bind;

import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.common.MoreAsserts;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;
import java.util.List;
import junit.framework.TestCase;

@SuppressWarnings("resource")
Expand Down Expand Up @@ -243,4 +249,15 @@ public void testJsonValue() throws IOException {
} catch (UnsupportedOperationException expected) {
}
}

/**
* {@link JsonTreeWriter} effectively replaces the complete writing logic of {@link JsonWriter} to
* create a {@link JsonElement} tree instead of writing to a {@link Writer}. Therefore all relevant
* methods of {@code JsonWriter} must be overridden.
*/
public void testOverrides() {
List<String> ignoredMethods = Arrays.asList("setLenient(boolean)", "isLenient()", "setIndent(java.lang.String)",
"setHtmlSafe(boolean)", "isHtmlSafe()", "setSerializeNulls(boolean)", "getSerializeNulls()");
MoreAsserts.assertOverridesMethods(JsonWriter.class, JsonTreeWriter.class, ignoredMethods);
}
}