Skip to content

Commit 50f7a02

Browse files
committed
Verify that isNaN works for CBOR, Smile too; still need to check Avro, Protobuf
1 parent 52f58f7 commit 50f7a02

File tree

3 files changed

+99
-57
lines changed

3 files changed

+99
-57
lines changed

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,23 @@ private int _readAndWriteBytes(OutputStream out, int total) throws IOException
15581558
/* Numeric accessors of public API
15591559
/**********************************************************
15601560
*/
1561-
1561+
1562+
@Override // since 2.9
1563+
public boolean isNaN() {
1564+
if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) {
1565+
if ((_numTypesValid & NR_DOUBLE) != 0) {
1566+
// 10-Mar-2017, tatu: Alas, `Double.isFinite(d)` only added in JDK 8
1567+
double d = _numberDouble;
1568+
return Double.isNaN(d) || Double.isInfinite(d);
1569+
}
1570+
if ((_numTypesValid & NR_FLOAT) != 0) {
1571+
float f = _numberFloat;
1572+
return Float.isNaN(f) || Float.isInfinite(f);
1573+
}
1574+
}
1575+
return false;
1576+
}
1577+
15621578
@Override
15631579
public Number getNumberValue() throws IOException
15641580
{

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

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,15 @@ public void testInt64Overflow() throws Exception
174174

175175
public void testDoubleValues() throws Exception
176176
{
177-
_verifyDouble(CBOR_F, 0.25);
178-
_verifyDouble(CBOR_F, 20.5);
179-
_verifyDouble(CBOR_F, -5000.25);
177+
_verifyDouble(CBOR_F, 0.25, false);
178+
_verifyDouble(CBOR_F, 20.5, false);
179+
_verifyDouble(CBOR_F, Double.NaN, true);
180+
_verifyDouble(CBOR_F, Double.POSITIVE_INFINITY, true);
181+
_verifyDouble(CBOR_F, Double.NEGATIVE_INFINITY, true);
182+
_verifyDouble(CBOR_F, -5000.25, false);
180183
}
181184

182-
private void _verifyDouble(CBORFactory f, double value) throws Exception
185+
private void _verifyDouble(CBORFactory f, double value, boolean isNaN) throws Exception
183186
{
184187
ByteArrayOutputStream out = new ByteArrayOutputStream();
185188
JsonGenerator gen = cborGenerator(f, out);
@@ -191,9 +194,11 @@ private void _verifyDouble(CBORFactory f, double value) throws Exception
191194
fail("Expected `NumberType.DOUBLE`, got "+p.getNumberType()+": "+p.getText());
192195
}
193196
assertEquals(value, p.getDoubleValue());
197+
assertEquals(isNaN, p.isNaN());
194198
assertEquals((float) value, p.getFloatValue());
195-
assertNull(p.nextToken());
196199

200+
assertNull(p.nextToken());
201+
197202
// also skip
198203
p = cborParser(f, out.toByteArray());
199204
assertEquals(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
@@ -207,9 +212,12 @@ public void testFloatValues() throws Exception
207212
// first, single-byte
208213
CBORFactory f = cborFactory();
209214
// single byte
210-
_verifyFloat(f, 0.25);
211-
_verifyFloat(f, 20.5);
212-
_verifyFloat(f, -5000.25);
215+
_verifyFloat(f, 0.25, false);
216+
_verifyFloat(f, 20.5, false);
217+
_verifyFloat(CBOR_F, Float.NaN, true);
218+
_verifyFloat(CBOR_F, Float.POSITIVE_INFINITY, true);
219+
_verifyFloat(CBOR_F, Float.NEGATIVE_INFINITY, true);
220+
_verifyFloat(f, -5000.25, false);
213221

214222
// But then, oddity: 16-bit mini-float
215223
// Examples from [https://en.wikipedia.org/wiki/Half_precision_floating-point_format]
@@ -223,7 +231,7 @@ public void testFloatValues() throws Exception
223231
// ... can add more, but need bit looser comparison if so
224232
}
225233

226-
private void _verifyFloat(CBORFactory f, double value) throws Exception
234+
private void _verifyFloat(CBORFactory f, double value, boolean isNaN) throws Exception
227235
{
228236
ByteArrayOutputStream out = new ByteArrayOutputStream();
229237
JsonGenerator gen = cborGenerator(f, out);
@@ -235,6 +243,7 @@ private void _verifyFloat(CBORFactory f, double value) throws Exception
235243
fail("Expected `NumberType.FLOAT`, got "+p.getNumberType()+": "+p.getText());
236244
}
237245
assertEquals((float) value, p.getFloatValue());
246+
assertEquals(isNaN, p.isNaN());
238247
assertEquals(value, p.getDoubleValue());
239248
assertNull(p.nextToken());
240249

@@ -253,8 +262,11 @@ private void _verifyHalfFloat(JsonFactory f, int i16, double value) throws IOExc
253262
(byte) (i16 >> 8), (byte) i16
254263
};
255264

265+
boolean expNaN = Double.isNaN(value) || Double.isInfinite(value);
266+
256267
JsonParser p = f.createParser(data);
257268
assertEquals(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
269+
assertEquals(expNaN, p.isNaN());
258270
assertEquals(NumberType.FLOAT, p.getNumberType());
259271
assertEquals(value, p.getDoubleValue());
260272
assertNull(p.nextToken());

smile/src/test/java/com/fasterxml/jackson/dataformat/smile/parse/NumberParsingTest.java

Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ public void testLongs() throws IOException
138138

139139
public void testArrayWithInts() throws IOException
140140
{
141-
byte[] data = _smileDoc("[ 1, 0, -1, 255, -999, "
142-
+Integer.MIN_VALUE+","+Integer.MAX_VALUE+","
143-
+Long.MIN_VALUE+", "+Long.MAX_VALUE+" ]");
141+
byte[] data = _smileDoc("[ 1, 0, -1, 255, -999, "
142+
+Integer.MIN_VALUE+","+Integer.MAX_VALUE+","
143+
+Long.MIN_VALUE+", "+Long.MAX_VALUE+" ]");
144144
SmileParser p = _smileParser(data);
145145
assertNull(p.getCurrentToken());
146146
assertToken(JsonToken.START_ARRAY, p.nextToken());
@@ -182,60 +182,74 @@ public void testArrayWithInts() throws IOException
182182

183183
public void testFloats() throws IOException
184184
{
185-
ByteArrayOutputStream bo = new ByteArrayOutputStream();
186-
SmileGenerator g = smileGenerator(bo, false);
187-
float value = 0.37f;
188-
g.writeNumber(value);
189-
g.close();
190-
byte[] data = bo.toByteArray();
191-
assertEquals(6, data.length);
185+
ByteArrayOutputStream bo = new ByteArrayOutputStream();
186+
SmileGenerator g = smileGenerator(bo, false);
187+
float value = 0.37f;
188+
g.writeNumber(value);
189+
g.close();
190+
byte[] data = bo.toByteArray();
191+
assertEquals(6, data.length);
192192

193-
SmileParser p = _smileParser(data);
194-
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
195-
assertEquals(JsonParser.NumberType.FLOAT, p.getNumberType());
196-
assertEquals(value, p.getFloatValue());
197-
p.close();
193+
SmileParser p = _smileParser(data);
194+
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
195+
assertFalse(p.isNaN());
196+
assertEquals(JsonParser.NumberType.FLOAT, p.getNumberType());
197+
assertEquals(value, p.getFloatValue());
198+
p.close();
198199
}
199200

200201
public void testDoubles() throws IOException
201202
{
202-
ByteArrayOutputStream bo = new ByteArrayOutputStream();
203-
SmileGenerator g = smileGenerator(bo, false);
204-
double value = -12.0986;
205-
g.writeNumber(value);
206-
g.close();
207-
byte[] data = bo.toByteArray();
208-
assertEquals(11, data.length);
203+
ByteArrayOutputStream bo = new ByteArrayOutputStream();
204+
SmileGenerator g = smileGenerator(bo, false);
205+
double value = -12.0986;
206+
g.writeNumber(value);
207+
g.close();
208+
byte[] data = bo.toByteArray();
209+
assertEquals(11, data.length);
209210

210-
SmileParser p = _smileParser(data);
211-
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
212-
assertEquals(JsonParser.NumberType.DOUBLE, p.getNumberType());
213-
assertEquals(value, p.getDoubleValue());
214-
p.close();
211+
SmileParser p = _smileParser(data);
212+
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
213+
assertFalse(p.isNaN());
214+
assertEquals(JsonParser.NumberType.DOUBLE, p.getNumberType());
215+
assertEquals(value, p.getDoubleValue());
216+
p.close();
215217
}
216-
218+
217219
public void testArrayWithDoubles() throws IOException
218220
{
219-
ByteArrayOutputStream bo = new ByteArrayOutputStream();
220-
SmileGenerator g = smileGenerator(bo, false);
221-
g.writeStartArray();
222-
g.writeNumber(0.1f);
223-
g.writeNumber(0.333);
224-
g.writeEndArray();
225-
g.close();
226-
byte[] data = bo.toByteArray();
227-
assertEquals(19, data.length);
221+
final double[] values = new double[] {
222+
0.1,
223+
0.333,
224+
Double.POSITIVE_INFINITY,
225+
Double.NaN,
226+
-2.5,
227+
Double.NEGATIVE_INFINITY
228+
};
229+
230+
ByteArrayOutputStream bo = new ByteArrayOutputStream();
231+
SmileGenerator g = smileGenerator(bo, false);
232+
g.writeStartArray();
233+
for (double d : values) {
234+
g.writeNumber(d);
235+
}
236+
g.close();
228237

229-
SmileParser p = _smileParser(data);
230-
assertToken(JsonToken.START_ARRAY, p.nextToken());
231-
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
232-
assertEquals(JsonParser.NumberType.FLOAT, p.getNumberType());
233-
assertEquals(0.1f, p.getFloatValue());
234-
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
235-
assertEquals(JsonParser.NumberType.DOUBLE, p.getNumberType());
236-
assertEquals(0.333, p.getDoubleValue());
237-
assertToken(JsonToken.END_ARRAY, p.nextToken());
238-
p.close();
238+
byte[] data = bo.toByteArray();
239+
// 10 bytes per double, array start, end
240+
// assertEquals(2 + values.length * 10, data.length);
241+
242+
SmileParser p = _smileParser(data);
243+
assertToken(JsonToken.START_ARRAY, p.nextToken());
244+
for (double exp : values) {
245+
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
246+
boolean expNaN = Double.isNaN(exp) || Double.isInfinite(exp);
247+
assertEquals(exp, p.getDoubleValue());
248+
assertEquals(expNaN, p.isNaN());
249+
}
250+
assertToken(JsonToken.END_ARRAY, p.nextToken());
251+
assertNull(p.nextToken());
252+
p.close();
239253
}
240254

241255
public void testObjectWithDoubles() throws IOException

0 commit comments

Comments
 (0)