1
1
package com .fasterxml .jackson .dataformat .cbor .parse ;
2
2
3
3
import java .lang .reflect .Field ;
4
+ import java .util .Random ;
4
5
5
6
import com .fasterxml .jackson .core .JsonFactory ;
6
7
import com .fasterxml .jackson .core .JsonParser ;
7
8
import com .fasterxml .jackson .core .JsonToken ;
9
+ import com .fasterxml .jackson .core .io .SerializedString ;
8
10
import com .fasterxml .jackson .core .sym .ByteQuadsCanonicalizer ;
11
+
9
12
import com .fasterxml .jackson .dataformat .cbor .CBORFactory ;
10
13
import com .fasterxml .jackson .dataformat .cbor .CBORParser ;
11
14
import com .fasterxml .jackson .dataformat .cbor .CBORTestBase ;
12
15
import com .fasterxml .jackson .dataformat .cbor .databind .CBORMapper ;
13
16
14
17
public class SymbolTableTest extends CBORTestBase
15
18
{
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
+
16
28
public void testSimpleDefault () throws Exception
17
29
{
18
30
final CBORMapper vanillaMapper = cborMapper ();
@@ -21,6 +33,8 @@ public void testSimpleDefault() throws Exception
21
33
// First: should have empty symbol table
22
34
try (JsonParser p = vanillaMapper .createParser (doc )) {
23
35
ByteQuadsCanonicalizer syms = _findSymbols (p );
36
+ assertTrue (syms .isCanonicalizing ()); // added in 2.13
37
+
24
38
assertEquals (0 , syms .size ());
25
39
assertEquals (0 , _findParent (syms ).size ());
26
40
@@ -66,22 +80,146 @@ public void testSimpleDefault() throws Exception
66
80
}
67
81
}
68
82
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
+
70
95
// [dataformats-binary#252]: should be able to prevent canonicalization
71
96
public void testSimpleNoCanonicalize () throws Exception
72
97
{
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 \u00F6 bar" , "Longer F\u00F6 \u00F6 bar" ,
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 ));
78
117
79
- try (JsonParser p = mapper .createParser (doc )) {
118
+ try (JsonParser p = NO_CAN_MAPPER .createParser (doc )) {
80
119
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 ());
82
188
}
83
189
}
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
+
85
223
// Helper method to dig up symbol table reference for tests, without
86
224
// exposing it to user code
87
225
private ByteQuadsCanonicalizer _findSymbols (JsonParser p ) throws Exception
0 commit comments