Skip to content

Commit c8bb517

Browse files
committed
ground work for #253
1 parent fe2e029 commit c8bb517

File tree

2 files changed

+160
-22
lines changed

2 files changed

+160
-22
lines changed

cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParserBootstrapper.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@
1414
public class CBORParserBootstrapper
1515
{
1616
/*
17-
/**********************************************************
17+
/**********************************************************************
1818
/* Configuration
19-
/**********************************************************
19+
/**********************************************************************
2020
*/
2121

2222
protected final IOContext _context;
2323
protected final InputStream _in;
2424

2525
/*
26-
/**********************************************************
26+
/**********************************************************************
2727
/* Input buffering
28-
/**********************************************************
28+
/**********************************************************************
2929
*/
3030

3131
protected final byte[] _inputBuffer;
@@ -38,9 +38,9 @@ public class CBORParserBootstrapper
3838
protected final boolean _bufferRecyclable;
3939

4040
/*
41-
/**********************************************************
41+
/**********************************************************************
4242
/* Input location
43-
/**********************************************************
43+
/**********************************************************************
4444
*/
4545

4646
/**
@@ -53,9 +53,9 @@ public class CBORParserBootstrapper
5353
protected int _inputProcessed;
5454

5555
/*
56-
/**********************************************************
56+
/**********************************************************************
5757
/* Life-cycle
58-
/**********************************************************
58+
/**********************************************************************
5959
*/
6060

6161
public CBORParserBootstrapper(IOContext ctxt, InputStream in)
@@ -104,9 +104,9 @@ public CBORParser constructParser(int factoryFeatures,
104104
}
105105

106106
/*
107-
/**********************************************************
107+
/**********************************************************************
108108
/* Encoding detection for data format auto-detection
109-
/**********************************************************
109+
/**********************************************************************
110110
*/
111111

112112
public static MatchStrength hasCBORFormat(InputAccessor acc) throws IOException
@@ -175,11 +175,11 @@ public static MatchStrength hasCBORFormat(InputAccessor acc) throws IOException
175175
}
176176
return MatchStrength.INCONCLUSIVE;
177177
}
178-
178+
179179
/*
180-
/**********************************************************
180+
/**********************************************************************
181181
/* Internal methods, raw input access
182-
/**********************************************************
182+
/**********************************************************************
183183
*/
184184

185185
protected boolean ensureLoaded(int minimum) throws IOException

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/SymbolTableTest.java

Lines changed: 147 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
11
package com.fasterxml.jackson.dataformat.cbor.parse;
22

33
import java.lang.reflect.Field;
4+
import java.util.Random;
45

56
import com.fasterxml.jackson.core.JsonFactory;
67
import com.fasterxml.jackson.core.JsonParser;
78
import com.fasterxml.jackson.core.JsonToken;
9+
import com.fasterxml.jackson.core.io.SerializedString;
810
import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer;
11+
912
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
1013
import com.fasterxml.jackson.dataformat.cbor.CBORParser;
1114
import com.fasterxml.jackson.dataformat.cbor.CBORTestBase;
1215
import com.fasterxml.jackson.dataformat.cbor.databind.CBORMapper;
1316

1417
public class SymbolTableTest extends CBORTestBase
1518
{
19+
static class Point {
20+
public int x, y;
21+
}
22+
23+
private final CBORMapper NO_CAN_MAPPER = CBORMapper.builder(CBORFactory.builder()
24+
.disable(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES)
25+
.build())
26+
.build();
27+
1628
public void testSimpleDefault() throws Exception
1729
{
1830
final CBORMapper vanillaMapper = cborMapper();
@@ -21,6 +33,8 @@ public void testSimpleDefault() throws Exception
2133
// First: should have empty symbol table
2234
try (JsonParser p = vanillaMapper.createParser(doc)) {
2335
ByteQuadsCanonicalizer syms = _findSymbols(p);
36+
assertTrue(syms.isCanonicalizing()); // added in 2.13
37+
2438
assertEquals(0, syms.size());
2539
assertEquals(0, _findParent(syms).size());
2640

@@ -66,22 +80,146 @@ public void testSimpleDefault() throws Exception
6680
}
6781
}
6882

69-
// !!! TODO:
83+
// [dataformats-binary#253]: should be able to prevent canonicalization
84+
// Assumption: there is still non-null symbol table, but has "no canonicalization"
85+
public void testNoCanonicalizeWithMapper() throws Exception
86+
{
87+
final byte[] doc = cborDoc(a2q("{ 'x':13, 'y':-999}"));
88+
try (JsonParser p = NO_CAN_MAPPER.createParser(doc)) {
89+
Point point = NO_CAN_MAPPER.readValue(p, Point.class);
90+
assertEquals(13, point.x);
91+
assertEquals(-999, point.y);
92+
}
93+
}
94+
7095
// [dataformats-binary#252]: should be able to prevent canonicalization
7196
public void testSimpleNoCanonicalize() throws Exception
7297
{
73-
final byte[] doc = cborDoc("{\"a\":1,\"b\":2}");
74-
final CBORMapper mapper = CBORMapper.builder(CBORFactory.builder()
75-
.disable(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES)
76-
.build())
77-
.build();
98+
// !!! TODO: enable
99+
if (true) {
100+
return;
101+
}
102+
final String[] fieldNames = new String[] {
103+
// Ascii, various lengths
104+
"abc", "abcd123", "abcdefghi123940963", "",
105+
// Unicode, also (2-byte ones ought to be ok)
106+
"F\u00F6\u00F6", "F\u00F6\u00F6bar", "Longer F\u00F6\u00F6bar",
107+
108+
// and then couple of longer names; total needs to exceed 64k
109+
generateName(77),
110+
generateName(2000),
111+
generateName(17000),
112+
generateName(23000),
113+
generateName(33033),
114+
"end", // just simple end marker
115+
};
116+
final byte[] doc = cborDoc(jsonFrom(fieldNames));
78117

79-
try (JsonParser p = mapper.createParser(doc)) {
118+
try (JsonParser p = NO_CAN_MAPPER.createParser(doc)) {
80119
ByteQuadsCanonicalizer syms = _findSymbols(p);
81-
assertEquals(0, syms.size());
120+
assertFalse(syms.isCanonicalizing()); // added in 2.13
121+
assertEquals(-1, syms.size());
122+
// also, should not have parent:
123+
assertNull(_findParent(syms));
124+
125+
assertToken(JsonToken.START_OBJECT, p.nextToken());
126+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
127+
assertEquals(fieldNames[0], p.currentName());
128+
// should NOT add
129+
assertEquals(-1, syms.size());
130+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
131+
assertEquals(0, p.getIntValue());
132+
133+
// and from thereon...
134+
for (int i = 1; i < fieldNames.length; ++i) {
135+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
136+
assertEquals(fieldNames[i], p.currentName());
137+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
138+
assertEquals(i, p.getIntValue());
139+
}
140+
assertToken(JsonToken.END_OBJECT, p.nextToken());
141+
assertNull(p.nextToken());
142+
143+
assertEquals(-1, syms.size());
144+
}
145+
146+
// But let's also try other accessors: first, nextName()
147+
try (JsonParser p = NO_CAN_MAPPER.createParser(doc)) {
148+
assertToken(JsonToken.START_OBJECT, p.nextToken());
149+
assertEquals(fieldNames[0], p.nextFieldName());
150+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
151+
assertEquals(0, p.getIntValue());
152+
153+
// and from thereon...
154+
for (int i = 1; i < fieldNames.length; ++i) {
155+
assertEquals(fieldNames[i], p.nextFieldName());
156+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
157+
assertEquals(i, p.getIntValue());
158+
}
159+
assertToken(JsonToken.END_OBJECT, p.nextToken());
160+
assertNull(p.nextToken());
161+
162+
assertEquals(-1, _findSymbols(p).size());
163+
}
164+
165+
// and then nextName(match)
166+
try (JsonParser p = NO_CAN_MAPPER.createParser(doc)) {
167+
assertToken(JsonToken.START_OBJECT, p.nextToken());
168+
assertTrue(p.nextFieldName(new SerializedString(fieldNames[0])));
169+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
170+
assertEquals(0, p.getIntValue());
171+
172+
// and then negative match
173+
assertFalse(p.nextFieldName(new SerializedString("bogus")));
174+
assertEquals(fieldNames[1], p.currentName());
175+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
176+
assertEquals(1, p.getIntValue());
177+
178+
// and from thereon...
179+
for (int i = 2; i < fieldNames.length; ++i) {
180+
assertEquals(fieldNames[i], p.nextFieldName());
181+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
182+
assertEquals(i, p.getIntValue());
183+
}
184+
assertToken(JsonToken.END_OBJECT, p.nextToken());
185+
assertNull(p.nextToken());
186+
187+
assertEquals(-1, _findSymbols(p).size());
82188
}
83189
}
84-
190+
191+
private String jsonFrom(String... fields) {
192+
StringBuilder sb = new StringBuilder();
193+
sb.append("{");
194+
195+
for (int i = 0, len = fields.length; i < len; ++i) {
196+
if (i > 0) {
197+
sb.append(",\n");
198+
}
199+
sb.append('"').append(fields[i]).append('"')
200+
.append(" : ").append(i);
201+
}
202+
sb.append("}");
203+
return sb.toString();
204+
}
205+
206+
private String generateName(int minLen)
207+
{
208+
StringBuilder sb = new StringBuilder();
209+
Random rnd = new Random(123);
210+
while (sb.length() < minLen) {
211+
int ch = rnd.nextInt(96);
212+
if (ch < 32) { // ascii (single byte)
213+
sb.append((char) (48 + ch));
214+
} else if (ch < 64) { // 2 byte
215+
sb.append((char) (128 + ch));
216+
} else { // 3 byte
217+
sb.append((char) (4000 + ch));
218+
}
219+
}
220+
return sb.toString();
221+
}
222+
85223
// Helper method to dig up symbol table reference for tests, without
86224
// exposing it to user code
87225
private ByteQuadsCanonicalizer _findSymbols(JsonParser p) throws Exception

0 commit comments

Comments
 (0)