/
JDKSerializabilityTest.java
296 lines (260 loc) · 10 KB
/
JDKSerializabilityTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
package tools.jackson.core;
import java.io.*;
import org.junit.jupiter.api.Test;
import tools.jackson.core.exc.StreamReadException;
import tools.jackson.core.exc.StreamWriteException;
import tools.jackson.core.io.ContentReference;
import tools.jackson.core.json.JsonFactory;
import tools.jackson.core.util.DefaultPrettyPrinter;
import tools.jackson.core.util.JsonRecyclerPools;
import tools.jackson.core.util.RecyclerPool;
import static org.junit.jupiter.api.Assertions.*;
/**
* Unit tests to verify that `JsonFactory` and abstractions it relies on
* may be JDK serialized/deserialized.
*/
class JDKSerializabilityTest
extends JUnit5TestBase
{
/*
/**********************************************************************
/* Main factory type(s)
/**********************************************************************
*/
@Test
void jsonFactorySerializable() throws Exception
{
JsonFactory f = new JsonFactory();
String origJson = "{\"simple\":[1,true,{}]}";
assertEquals(origJson, _copyJson(f, origJson, false));
// Ok: freeze dry factory, thaw, and try to use again:
byte[] frozen = jdkSerialize(f);
JsonFactory f2 = jdkDeserialize(frozen);
assertNotNull(f2);
assertEquals(origJson, _copyJson(f2, origJson, false));
// Let's also try byte-based variant, for fun...
assertEquals(origJson, _copyJson(f2, origJson, true));
}
/*
/**********************************************************************
/* Parser-related types
/**********************************************************************
*/
@Test
void base64Variant() throws Exception
{
{
Base64Variant orig = Base64Variants.PEM;
final String exp = _encodeBase64(orig);
byte[] stuff = jdkSerialize(orig);
Base64Variant back = jdkDeserialize(stuff);
assertSame(orig, back);
assertEquals(exp, _encodeBase64(back));
}
// and then with a twist
{
Base64Variant orig = Base64Variants.MODIFIED_FOR_URL;
assertFalse(orig.usesPadding());
Base64Variant mod = orig.withWritePadding(true);
assertTrue(mod.usesPadding());
assertNotSame(orig, mod);
assertNotEquals(orig, mod);
assertNotEquals(mod, orig);
final String exp = _encodeBase64(mod);
byte[] stuff = jdkSerialize(mod);
Base64Variant back = jdkDeserialize(stuff);
assertTrue(back.usesPadding());
assertNotSame(mod, back);
assertEquals(mod, back);
assertEquals(exp, _encodeBase64(back));
}
}
@Test
void prettyPrinter() throws Exception
{
PrettyPrinter p = new DefaultPrettyPrinter();
byte[] stuff = jdkSerialize(p);
PrettyPrinter back = jdkDeserialize(stuff);
// what should we test?
assertNotNull(back);
}
@Test
void location() throws Exception
{
JsonFactory jf = new JsonFactory();
JsonParser jp = jf.createParser(ObjectReadContext.empty(), " { }");
assertToken(JsonToken.START_OBJECT, jp.nextToken());
JsonLocation loc = jp.currentLocation();
byte[] stuff = jdkSerialize(loc);
JsonLocation loc2 = jdkDeserialize(stuff);
assertNotNull(loc2);
assertEquals(loc.getLineNr(), loc2.getLineNr());
assertEquals(loc.getColumnNr(), loc2.getColumnNr());
jp.close();
}
@Test
void sourceReference() throws Exception
{
ContentReference ref = ContentReference.construct(true, "text",
ErrorReportConfiguration.defaults());
byte[] stuff = jdkSerialize(ref);
ContentReference ref2 = jdkDeserialize(stuff);
assertNotNull(ref2);
assertSame(ref2, ContentReference.unknown());
}
/*
/**********************************************************************
/* Other entities
/**********************************************************************
*/
@Test
void recyclerPools() throws Exception
{
// First: shared/global pools that will always remain/become globally
// shared instances
_testRecyclerPoolGlobal(JsonRecyclerPools.nonRecyclingPool());
_testRecyclerPoolGlobal(JsonRecyclerPools.threadLocalPool());
_testRecyclerPoolGlobal(JsonRecyclerPools.sharedConcurrentDequePool());
_testRecyclerPoolGlobal(JsonRecyclerPools.sharedLockFreePool());
JsonRecyclerPools.BoundedPool bounded = (JsonRecyclerPools.BoundedPool)
_testRecyclerPoolGlobal(JsonRecyclerPools.sharedBoundedPool());
assertEquals(RecyclerPool.BoundedPoolBase.DEFAULT_CAPACITY, bounded.capacity());
_testRecyclerPoolNonShared(JsonRecyclerPools.newConcurrentDequePool());
_testRecyclerPoolNonShared(JsonRecyclerPools.newLockFreePool());
bounded = (JsonRecyclerPools.BoundedPool)
_testRecyclerPoolNonShared(JsonRecyclerPools.newBoundedPool(250));
assertEquals(250, bounded.capacity());
}
private <T extends RecyclerPool<?>> T _testRecyclerPoolGlobal(T pool) throws Exception {
byte[] stuff = jdkSerialize(pool);
T result = jdkDeserialize(stuff);
assertNotNull(result);
assertSame(pool.getClass(), result.getClass());
return result;
}
private <T extends RecyclerPool<?>> T _testRecyclerPoolNonShared(T pool) throws Exception {
byte[] stuff = jdkSerialize(pool);
T result = jdkDeserialize(stuff);
assertNotNull(result);
assertEquals(pool.getClass(), result.getClass());
assertNotSame(pool, result);
return result;
}
/*
/**********************************************************************
/* Exception types
/**********************************************************************
*/
@Test
void parseException() throws Exception
{
JsonFactory jf = new JsonFactory();
JsonParser p = jf.createParser(ObjectReadContext.empty(), " { garbage! }");
StreamReadException exc = null;
try {
p.nextToken();
p.nextToken();
fail("Should not get here");
} catch (StreamReadException e) {
exc = e;
}
p.close();
byte[] stuff = jdkSerialize(exc);
StreamReadException result = jdkDeserialize(stuff);
assertNotNull(result);
}
@Test
void generationException() throws Exception
{
JsonFactory jf = new JsonFactory();
JsonGenerator g = jf.createGenerator(ObjectWriteContext.empty(), new ByteArrayOutputStream());
StreamWriteException exc = null;
g.writeStartObject();
try {
g.writeNumber(4);
fail("Should not get here");
} catch (StreamWriteException e) {
exc = e;
}
g.close();
byte[] stuff = jdkSerialize(exc);
StreamWriteException result = jdkDeserialize(stuff);
assertNotNull(result);
}
/*
/**********************************************************************
/* Misc other types
/**********************************************************************
*/
@Test
void pointerSerializationNonEmpty() throws Exception
{
// First, see that we can write and read a general JsonPointer
final String INPUT = "/Image/15/name";
JsonPointer original = JsonPointer.compile(INPUT);
byte[] ser = jdkSerialize(original);
JsonPointer copy = jdkDeserialize(ser);
assertNotSame(copy, original);
assertEquals(original, copy);
assertEquals(original.hashCode(), copy.hashCode());
// 11-Oct-2022, tatu: Let's verify sub-path serializations too,
// since 2.14 has rewritten internal implementation
JsonPointer branch = original.tail();
assertEquals("/15/name", branch.toString());
ser = jdkSerialize(branch);
copy = jdkDeserialize(ser);
assertEquals("/15/name", copy.toString());
assertEquals(branch, copy);
assertEquals(branch.hashCode(), copy.hashCode());
JsonPointer leaf = branch.tail();
assertEquals("/name", leaf.toString());
ser = jdkSerialize(leaf);
copy = jdkDeserialize(ser);
assertEquals("/name", copy.toString());
assertEquals(leaf, copy);
assertEquals(leaf.hashCode(), copy.hashCode());
}
@Test
void pointerSerializationEmpty() throws Exception
{
// and then verify that "empty" instance gets canonicalized
final JsonPointer emptyP = JsonPointer.empty();
byte[] ser = jdkSerialize(emptyP);
JsonPointer result = jdkDeserialize(ser);
assertSame(emptyP, result,
"Should get same 'empty' instance when JDK serialize+deserialize");
}
/*
/**********************************************************************
/* Helper methods
/**********************************************************************
*/
@SuppressWarnings("resource")
protected String _copyJson(JsonFactory f, String json, boolean useBytes) throws IOException
{
if (useBytes) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
JsonGenerator jg = f.createGenerator(ObjectWriteContext.empty(), bytes);
_copyJson(f, json, jg);
return bytes.toString("UTF-8");
}
StringWriter sw = new StringWriter();
JsonGenerator jg = f.createGenerator(ObjectWriteContext.empty(), sw);
_copyJson(f, json, jg);
return sw.toString();
}
protected void _copyJson(JsonFactory f, String json, JsonGenerator g) throws IOException
{
JsonParser p = f.createParser(ObjectReadContext.empty(), json);
while (p.nextToken() != null) {
g.copyCurrentEvent(p);
}
p.close();
g.close();
}
protected String _encodeBase64(Base64Variant b64) throws IOException
{
// something with padding...
return b64.encode("abcde".getBytes("UTF-8"));
}
}