Skip to content

Commit d84e26d

Browse files
authored
Issue 1242: Printing Gson version when throwing AssertionError and IllegalArgumentException (#1321)
On some versions of Android (probably on some variants of the popular Samsung S4 phone), an older version of Gson is suspected to be bundled in, and gets picked up from the system classpath. For those versions, the applications that include the latest Gson fail unexpectedly. This debug print will help confirm this issue.
1 parent 1215841 commit d84e26d

File tree

5 files changed

+185
-2
lines changed

5 files changed

+185
-2
lines changed

gson/pom.xml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<scope>test</scope>
1818
</dependency>
1919
</dependencies>
20-
20+
2121
<build>
2222
<plugins>
2323
<plugin>
@@ -56,6 +56,23 @@
5656
<groupId>org.apache.felix</groupId>
5757
<artifactId>maven-bundle-plugin</artifactId>
5858
</plugin>
59+
<plugin>
60+
<groupId>org.codehaus.mojo</groupId>
61+
<artifactId>templating-maven-plugin</artifactId>
62+
<version>1.0.0</version>
63+
<executions>
64+
<execution>
65+
<id>filtering-java-templates</id>
66+
<goals>
67+
<goal>filter-sources</goal>
68+
</goals>
69+
<configuration>
70+
<sourceDirectory>${basedir}/src/main/java-templates</sourceDirectory>
71+
<outputDirectory>${project.build.directory}/generated-sources/java-templates</outputDirectory>
72+
</configuration>
73+
</execution>
74+
</executions>
75+
</plugin>
5976
</plugins>
6077
</build>
6178
</project>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (C) 2018 The Gson authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.gson.internal;
18+
19+
/**
20+
* Build configuration for Gson. This file is automatically populated by
21+
* templating-maven-plugin and .java/.class files are generated for use in Gson.
22+
*
23+
* @author Inderjeet Singh
24+
*/
25+
public final class GsonBuildConfig {
26+
// Based on https://stackoverflow.com/questions/2469922/generate-a-version-java-file-in-maven
27+
28+
/** This field is automatically populated by Maven when a build is triggered */
29+
public static final String VERSION = "${project.version}";
30+
}

gson/src/main/java/com/google/gson/Gson.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
import com.google.gson.internal.ConstructorConstructor;
3939
import com.google.gson.internal.Excluder;
40+
import com.google.gson.internal.GsonBuildConfig;
4041
import com.google.gson.internal.Primitives;
4142
import com.google.gson.internal.Streams;
4243
import com.google.gson.internal.bind.ArrayTypeAdapter;
@@ -461,7 +462,7 @@ public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
461462
return candidate;
462463
}
463464
}
464-
throw new IllegalArgumentException("GSON cannot handle " + type);
465+
throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
465466
} finally {
466467
threadCalls.remove(type);
467468

@@ -703,6 +704,8 @@ public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOE
703704
((TypeAdapter<Object>) adapter).write(writer, src);
704705
} catch (IOException e) {
705706
throw new JsonIOException(e);
707+
} catch (AssertionError e) {
708+
throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
706709
} finally {
707710
writer.setLenient(oldLenient);
708711
writer.setHtmlSafe(oldHtmlSafe);
@@ -779,6 +782,8 @@ public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOExce
779782
Streams.write(jsonElement, writer);
780783
} catch (IOException e) {
781784
throw new JsonIOException(e);
785+
} catch (AssertionError e) {
786+
throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
782787
} finally {
783788
writer.setLenient(oldLenient);
784789
writer.setHtmlSafe(oldHtmlSafe);
@@ -935,6 +940,8 @@ public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, J
935940
} catch (IOException e) {
936941
// TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException
937942
throw new JsonSyntaxException(e);
943+
} catch (AssertionError e) {
944+
throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
938945
} finally {
939946
reader.setLenient(oldLenient);
940947
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (C) 2018 Gson Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.gson.functional;
17+
18+
import java.io.IOException;
19+
import java.util.regex.Pattern;
20+
21+
import org.junit.Before;
22+
import org.junit.Test;
23+
24+
import com.google.gson.Gson;
25+
import com.google.gson.GsonBuilder;
26+
import com.google.gson.TypeAdapter;
27+
import com.google.gson.stream.JsonReader;
28+
import com.google.gson.stream.JsonWriter;
29+
30+
import junit.framework.TestCase;
31+
32+
/**
33+
* Functional tests to validate printing of Gson version on AssertionErrors
34+
*
35+
* @author Inderjeet Singh
36+
*/
37+
public class GsonVersionDiagnosticsTest extends TestCase {
38+
private static final Pattern GSON_VERSION_PATTERN = Pattern.compile("(\\(GSON \\d\\.\\d\\.\\d)(?:[-.][A-Z]+)?\\)$");
39+
40+
private Gson gson;
41+
42+
@Before
43+
public void setUp() {
44+
gson = new GsonBuilder().registerTypeAdapter(TestType.class, new TypeAdapter<TestType>() {
45+
@Override public void write(JsonWriter out, TestType value) {
46+
throw new AssertionError("Expected during serialization");
47+
}
48+
@Override public TestType read(JsonReader in) throws IOException {
49+
throw new AssertionError("Expected during deserialization");
50+
}
51+
}).create();
52+
}
53+
54+
@Test
55+
public void testVersionPattern() {
56+
assertTrue(GSON_VERSION_PATTERN.matcher("(GSON 2.8.5)").matches());
57+
assertTrue(GSON_VERSION_PATTERN.matcher("(GSON 2.8.5-SNAPSHOT)").matches());
58+
}
59+
60+
@Test
61+
public void testAssertionErrorInSerializationPrintsVersion() {
62+
try {
63+
gson.toJson(new TestType());
64+
fail();
65+
} catch (AssertionError expected) {
66+
ensureAssertionErrorPrintsGsonVersion(expected);
67+
}
68+
}
69+
70+
@Test
71+
public void testAssertionErrorInDeserializationPrintsVersion() {
72+
try {
73+
gson.fromJson("{'a':'abc'}", TestType.class);
74+
fail();
75+
} catch (AssertionError expected) {
76+
ensureAssertionErrorPrintsGsonVersion(expected);
77+
}
78+
}
79+
80+
private void ensureAssertionErrorPrintsGsonVersion(AssertionError expected) {
81+
String msg = expected.getMessage();
82+
// System.err.println(msg);
83+
int start = msg.indexOf("(GSON");
84+
assertTrue(start > 0);
85+
int end = msg.indexOf("):") + 1;
86+
assertTrue(end > 0 && end > start + 6);
87+
String version = msg.substring(start, end);
88+
// System.err.println(version);
89+
assertTrue(GSON_VERSION_PATTERN.matcher(version).matches());
90+
}
91+
92+
private static final class TestType {
93+
@SuppressWarnings("unused")
94+
String a;
95+
}
96+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (C) 2018 The Gson authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.gson.internal;
17+
18+
import static org.junit.Assert.assertFalse;
19+
20+
import org.junit.Test;
21+
22+
/**
23+
* Unit tests for {@code GsonBuildConfig}
24+
*
25+
* @author Inderjeet Singh
26+
*/
27+
public class GsonBuildConfigTest {
28+
29+
@Test
30+
public void testEnsureGsonBuildConfigGetsUpdatedToMavenVersion() {
31+
assertFalse("${project.version}".equals(GsonBuildConfig.VERSION));
32+
}
33+
}

0 commit comments

Comments
 (0)