xref: /aosp_15_r20/external/jackson-databind/src/test/java/com/fasterxml/jackson/databind/BaseTest.java (revision 0ed15c778abdfe0f5f51f6133673e1619d6e56e4)
1 package com.fasterxml.jackson.databind;
2 
3 import java.io.*;
4 import java.util.Arrays;
5 
6 import junit.framework.TestCase;
7 
8 import com.fasterxml.jackson.core.*;
9 
10 //import static org.junit.Assert.*;
11 
12 public abstract class BaseTest
13     extends TestCase
14 {
15     /*
16     /**********************************************************
17     /* Some sample documents:
18     /**********************************************************
19      */
20 
21     protected final static int SAMPLE_SPEC_VALUE_WIDTH = 800;
22     protected final static int SAMPLE_SPEC_VALUE_HEIGHT = 600;
23     protected final static String SAMPLE_SPEC_VALUE_TITLE = "View from 15th Floor";
24     protected final static String SAMPLE_SPEC_VALUE_TN_URL = "http://www.example.com/image/481989943";
25     protected final static int SAMPLE_SPEC_VALUE_TN_HEIGHT = 125;
26     protected final static String SAMPLE_SPEC_VALUE_TN_WIDTH = "100";
27     protected final static int SAMPLE_SPEC_VALUE_TN_ID1 = 116;
28     protected final static int SAMPLE_SPEC_VALUE_TN_ID2 = 943;
29     protected final static int SAMPLE_SPEC_VALUE_TN_ID3 = 234;
30     protected final static int SAMPLE_SPEC_VALUE_TN_ID4 = 38793;
31 
32     protected final static String SAMPLE_DOC_JSON_SPEC =
33         "{\n"
34         +"  \"Image\" : {\n"
35         +"    \"Width\" : "+SAMPLE_SPEC_VALUE_WIDTH+",\n"
36         +"    \"Height\" : "+SAMPLE_SPEC_VALUE_HEIGHT+","
37         +"\"Title\" : \""+SAMPLE_SPEC_VALUE_TITLE+"\",\n"
38         +"    \"Thumbnail\" : {\n"
39         +"      \"Url\" : \""+SAMPLE_SPEC_VALUE_TN_URL+"\",\n"
40         +"\"Height\" : "+SAMPLE_SPEC_VALUE_TN_HEIGHT+",\n"
41         +"      \"Width\" : \""+SAMPLE_SPEC_VALUE_TN_WIDTH+"\"\n"
42         +"    },\n"
43         +"    \"IDs\" : ["+SAMPLE_SPEC_VALUE_TN_ID1+","+SAMPLE_SPEC_VALUE_TN_ID2+","+SAMPLE_SPEC_VALUE_TN_ID3+","+SAMPLE_SPEC_VALUE_TN_ID4+"]\n"
44         +"  }"
45         +"}"
46         ;
47 
48     /*
49     /**********************************************************
50     /* Helper classes (beans)
51     /**********************************************************
52      */
53 
54     /**
55      * Sample class from Jackson tutorial ("JacksonInFiveMinutes")
56      */
57     protected static class FiveMinuteUser {
58         public enum Gender { MALE, FEMALE };
59 
60         public static class Name
61         {
62             private String _first, _last;
63 
Name()64             public Name() { }
Name(String f, String l)65             public Name(String f, String l) {
66                 _first = f;
67                 _last = l;
68             }
69 
getFirst()70             public String getFirst() { return _first; }
getLast()71             public String getLast() { return _last; }
72 
setFirst(String s)73             public void setFirst(String s) { _first = s; }
setLast(String s)74             public void setLast(String s) { _last = s; }
75 
76             @Override
equals(Object o)77             public boolean equals(Object o)
78             {
79                 if (o == this) return true;
80                 if (o == null || o.getClass() != getClass()) return false;
81                 Name other = (Name) o;
82                 return _first.equals(other._first) && _last.equals(other._last);
83             }
84         }
85 
86         private Gender _gender;
87         private Name _name;
88         private boolean _isVerified;
89         private byte[] _userImage;
90 
FiveMinuteUser()91         public FiveMinuteUser() { }
92 
FiveMinuteUser(String first, String last, boolean verified, Gender g, byte[] data)93         public FiveMinuteUser(String first, String last, boolean verified, Gender g, byte[] data)
94         {
95             _name = new Name(first, last);
96             _isVerified = verified;
97             _gender = g;
98             _userImage = data;
99         }
100 
getName()101         public Name getName() { return _name; }
isVerified()102         public boolean isVerified() { return _isVerified; }
getGender()103         public Gender getGender() { return _gender; }
getUserImage()104         public byte[] getUserImage() { return _userImage; }
105 
setName(Name n)106         public void setName(Name n) { _name = n; }
setVerified(boolean b)107         public void setVerified(boolean b) { _isVerified = b; }
setGender(Gender g)108         public void setGender(Gender g) { _gender = g; }
setUserImage(byte[] b)109         public void setUserImage(byte[] b) { _userImage = b; }
110 
111         @Override
equals(Object o)112         public boolean equals(Object o)
113         {
114             if (o == this) return true;
115             if (o == null || o.getClass() != getClass()) return false;
116             FiveMinuteUser other = (FiveMinuteUser) o;
117             if (_isVerified != other._isVerified) return false;
118             if (_gender != other._gender) return false;
119             if (!_name.equals(other._name)) return false;
120             byte[] otherImage = other._userImage;
121             if (otherImage.length != _userImage.length) return false;
122             for (int i = 0, len = _userImage.length; i < len; ++i) {
123                 if (_userImage[i] != otherImage[i]) {
124                     return false;
125                 }
126             }
127             return true;
128         }
129     }
130 
131     /*
132     /**********************************************************
133     /* High-level helpers
134     /**********************************************************
135      */
136 
verifyJsonSpecSampleDoc(JsonParser jp, boolean verifyContents)137     protected void verifyJsonSpecSampleDoc(JsonParser jp, boolean verifyContents)
138         throws IOException
139     {
140         verifyJsonSpecSampleDoc(jp, verifyContents, true);
141     }
142 
verifyJsonSpecSampleDoc(JsonParser jp, boolean verifyContents, boolean requireNumbers)143     protected void verifyJsonSpecSampleDoc(JsonParser jp, boolean verifyContents,
144             boolean requireNumbers)
145         throws IOException
146     {
147         if (!jp.hasCurrentToken()) {
148             jp.nextToken();
149         }
150         assertToken(JsonToken.START_OBJECT, jp.currentToken()); // main object
151 
152         assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Image'
153         if (verifyContents) {
154             verifyFieldName(jp, "Image");
155         }
156 
157         assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'image' object
158 
159         assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width'
160         if (verifyContents) {
161             verifyFieldName(jp, "Width");
162         }
163 
164         verifyIntToken(jp.nextToken(), requireNumbers);
165         if (verifyContents) {
166             verifyIntValue(jp, SAMPLE_SPEC_VALUE_WIDTH);
167         }
168 
169         assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height'
170         if (verifyContents) {
171             verifyFieldName(jp, "Height");
172         }
173 
174         verifyIntToken(jp.nextToken(), requireNumbers);
175         if (verifyContents) {
176             verifyIntValue(jp, SAMPLE_SPEC_VALUE_HEIGHT);
177         }
178         assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Title'
179         if (verifyContents) {
180             verifyFieldName(jp, "Title");
181         }
182         assertToken(JsonToken.VALUE_STRING, jp.nextToken());
183         assertEquals(SAMPLE_SPEC_VALUE_TITLE, getAndVerifyText(jp));
184         assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Thumbnail'
185         if (verifyContents) {
186             verifyFieldName(jp, "Thumbnail");
187         }
188 
189         assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'thumbnail' object
190         assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Url'
191         if (verifyContents) {
192             verifyFieldName(jp, "Url");
193         }
194         assertToken(JsonToken.VALUE_STRING, jp.nextToken());
195         if (verifyContents) {
196             assertEquals(SAMPLE_SPEC_VALUE_TN_URL, getAndVerifyText(jp));
197         }
198         assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height'
199         if (verifyContents) {
200             verifyFieldName(jp, "Height");
201         }
202         verifyIntToken(jp.nextToken(), requireNumbers);
203         if (verifyContents) {
204             verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_HEIGHT);
205         }
206         assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width'
207         if (verifyContents) {
208             verifyFieldName(jp, "Width");
209         }
210         // Width value is actually a String in the example
211         assertToken(JsonToken.VALUE_STRING, jp.nextToken());
212         if (verifyContents) {
213             assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, getAndVerifyText(jp));
214         }
215 
216         assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'thumbnail' object
217         assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'IDs'
218         assertToken(JsonToken.START_ARRAY, jp.nextToken()); // 'ids' array
219         verifyIntToken(jp.nextToken(), requireNumbers); // ids[0]
220         if (verifyContents) {
221             verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID1);
222         }
223         verifyIntToken(jp.nextToken(), requireNumbers); // ids[1]
224         if (verifyContents) {
225             verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID2);
226         }
227         verifyIntToken(jp.nextToken(), requireNumbers); // ids[2]
228         if (verifyContents) {
229             verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID3);
230         }
231         verifyIntToken(jp.nextToken(), requireNumbers); // ids[3]
232         if (verifyContents) {
233             verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID4);
234         }
235         assertToken(JsonToken.END_ARRAY, jp.nextToken()); // 'ids' array
236 
237         assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'image' object
238 
239         assertToken(JsonToken.END_OBJECT, jp.nextToken()); // main object
240     }
241 
verifyIntToken(JsonToken t, boolean requireNumbers)242     private void verifyIntToken(JsonToken t, boolean requireNumbers)
243     {
244         if (t == JsonToken.VALUE_NUMBER_INT) {
245             return;
246         }
247         if (requireNumbers) { // to get error
248             assertToken(JsonToken.VALUE_NUMBER_INT, t);
249         }
250         // if not number, must be String
251         if (t != JsonToken.VALUE_STRING) {
252             fail("Expected INT or STRING value, got "+t);
253         }
254     }
255 
verifyFieldName(JsonParser p, String expName)256     protected void verifyFieldName(JsonParser p, String expName)
257         throws IOException
258     {
259         assertEquals(expName, p.getText());
260         assertEquals(expName, p.currentName());
261     }
262 
verifyIntValue(JsonParser p, long expValue)263     protected void verifyIntValue(JsonParser p, long expValue)
264         throws IOException
265     {
266         // First, via textual
267         assertEquals(String.valueOf(expValue), p.getText());
268     }
269 
270     /*
271     /**********************************************************
272     /* Parser/generator construction
273     /**********************************************************
274      */
275 
createParserUsingReader(String input)276     protected JsonParser createParserUsingReader(String input)
277         throws IOException, JsonParseException
278     {
279         return createParserUsingReader(new JsonFactory(), input);
280     }
281 
createParserUsingReader(JsonFactory f, String input)282     protected JsonParser createParserUsingReader(JsonFactory f, String input)
283         throws IOException
284     {
285         return f.createParser(new StringReader(input));
286     }
287 
createParserUsingStream(String input, String encoding)288     protected JsonParser createParserUsingStream(String input, String encoding)
289         throws IOException
290     {
291         return createParserUsingStream(new JsonFactory(), input, encoding);
292     }
293 
createParserUsingStream(JsonFactory f, String input, String encoding)294     protected JsonParser createParserUsingStream(JsonFactory f,
295             String input, String encoding)
296         throws IOException
297     {
298         /* 23-Apr-2008, tatus: UTF-32 is not supported by JDK, have to
299          *   use our own codec too (which is not optimal since there's
300          *   a chance both encoder and decoder might have bugs, but ones
301          *   that cancel each other out or such)
302          */
303         byte[] data;
304         if (encoding.equalsIgnoreCase("UTF-32")) {
305             data = encodeInUTF32BE(input);
306         } else {
307             data = input.getBytes(encoding);
308         }
309         InputStream is = new ByteArrayInputStream(data);
310         return f.createParser(is);
311     }
312 
313     /*
314     /**********************************************************
315     /* Additional assertion methods
316     /**********************************************************
317      */
318 
assertToken(JsonToken expToken, JsonToken actToken)319     protected void assertToken(JsonToken expToken, JsonToken actToken)
320     {
321         if (actToken != expToken) {
322             fail("Expected token "+expToken+", current token "+actToken);
323         }
324     }
325 
assertToken(JsonToken expToken, JsonParser jp)326     protected void assertToken(JsonToken expToken, JsonParser jp)
327     {
328         assertToken(expToken, jp.currentToken());
329     }
330 
assertType(Object ob, Class<?> expType)331     protected void assertType(Object ob, Class<?> expType)
332     {
333         if (ob == null) {
334             fail("Expected an object of type "+expType.getName()+", got null");
335         }
336         Class<?> cls = ob.getClass();
337         if (!expType.isAssignableFrom(cls)) {
338             fail("Expected type "+expType.getName()+", got "+cls.getName());
339         }
340     }
341 
assertValidLocation(JsonLocation location)342     protected void assertValidLocation(JsonLocation location) {
343         assertNotNull("Should have non-null location", location);
344         assertTrue("Should have positive line number", location.getLineNr() > 0);
345     }
346 
verifyException(Throwable e, String... matches)347     public static void verifyException(Throwable e, String... matches)
348     {
349         String msg = e.getMessage();
350         String lmsg = (msg == null) ? "" : msg.toLowerCase();
351         for (String match : matches) {
352             String lmatch = match.toLowerCase();
353             if (lmsg.indexOf(lmatch) >= 0) {
354                 return;
355             }
356         }
357         fail("Expected an exception with one of substrings ("
358                 +Arrays.asList(matches)+"): got one (of type "+e.getClass().getName()
359                 +") with message \""+msg+"\"");
360     }
361 
362     /**
363      * Method that gets textual contents of the current token using
364      * available methods, and ensures results are consistent, before
365      * returning them
366      */
getAndVerifyText(JsonParser jp)367     protected String getAndVerifyText(JsonParser jp)
368         throws IOException, JsonParseException
369     {
370         // Ok, let's verify other accessors
371         int actLen = jp.getTextLength();
372         char[] ch = jp.getTextCharacters();
373         String str2 = new String(ch, jp.getTextOffset(), actLen);
374         String str = jp.getText();
375 
376         if (str.length() !=  actLen) {
377             fail("Internal problem (jp.token == "+jp.currentToken()+"): jp.getText().length() ['"+str+"'] == "+str.length()+"; jp.getTextLength() == "+actLen);
378         }
379         assertEquals("String access via getText(), getTextXxx() must be the same", str, str2);
380 
381         return str;
382     }
383 
384     /*
385     /**********************************************************
386     /* And other helpers
387     /**********************************************************
388      */
389 
encodeInUTF32BE(String input)390     protected byte[] encodeInUTF32BE(String input)
391     {
392         int len = input.length();
393         byte[] result = new byte[len * 4];
394         int ptr = 0;
395         for (int i = 0; i < len; ++i, ptr += 4) {
396             char c = input.charAt(i);
397             result[ptr] = result[ptr+1] = (byte) 0;
398             result[ptr+2] = (byte) (c >> 8);
399             result[ptr+3] = (byte) c;
400         }
401         return result;
402     }
403 
quote(String str)404     public String quote(String str) {
405         return '"'+str+'"';
406     }
407 }
408