-
Notifications
You must be signed in to change notification settings - Fork 134
Expand file tree
/
Copy pathJsonWireDoubleAndFloatSpecialValuesAcceptanceTests.java
More file actions
222 lines (187 loc) · 8.5 KB
/
Copy pathJsonWireDoubleAndFloatSpecialValuesAcceptanceTests.java
File metadata and controls
222 lines (187 loc) · 8.5 KB
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
/*
* Copyright 2013-2025 chronicle.software; SPDX-License-Identifier: Apache-2.0
*/
package net.openhft.chronicle.wire;
import net.openhft.chronicle.bytes.Bytes;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.function.DoublePredicate;
import java.util.function.Predicate;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Acceptance tests for JSON Wire Double and Float special value handling, e.g. NaN, Infinity.
* <p>
* For implementation details please see:
* <ul>
* <li>{@link YamlWireOut.YamlValueOut#float64(double)}</li>
* <li>{@link YamlWireOut.YamlValueOut#float32(float)}</li>
* <li>{@link YamlWire.YamlValueOut#writeSpecialDoubleValueToBytes(Bytes, double)} </li>
* <li>{@link YamlWire.YamlValueOut#writeSpecialFloatValueToBytes(Bytes, float)} </li>
* <li>{@link JSONWire.JSONValueOut#writeSpecialDoubleValueToBytes(Bytes, double)} </li>
* <li>{@link JSONWire.JSONValueOut#writeSpecialFloatValueToBytes(Bytes, float)} </li>
* </ul>
*/
class JsonWireDoubleAndFloatSpecialValuesAcceptanceTests {
@ParameterizedTest
@MethodSource("doubleTestInputs")
void serialiseDoubleSpecialValues(DoubleTestInput doubleTestInput) {
assertEquals(
String.format("\"%s\"", doubleTestInput.expectedStringRepresentation),
toJson(doubleTestInput.inputValue),
"Expected correct representation for special value and for it to be quoted as a string literal"
);
}
@ParameterizedTest
@MethodSource("floatTestInputs")
void serialiseFloatSpecialValues(FloatTestInput floatTestInput) {
assertEquals(
String.format("\"%s\"", floatTestInput.expectedStringRepresentation),
toJson(floatTestInput.inputValue),
"Expected correct representation for special value and for it to be quoted as a string literal"
);
}
@ParameterizedTest
@MethodSource("doubleTestInputs")
void doubleRoundTrip(DoubleTestInput doubleTestInput) {
// Serialise an object to JSON and ensure its represented correctly
JSONWire inputWire = new JSONWire();
inputWire.getValueOut().object(new DoubleDto(doubleTestInput.inputValue));
String text = JSONWire.asText(inputWire);
assertEquals(
String.format("{\"value\":\"%s\"}", doubleTestInput.expectedStringRepresentation),
text,
"Expected JSON representation where special values are quoted string literals"
);
// Deserialize back to an object, ensure that the special value is retained
JSONWire outputWire = JSONWire.from(text);
DoubleDto object = outputWire.getValueIn().object(DoubleDto.class);
Assertions.assertNotNull(object);
Assertions.assertTrue(doubleTestInput.expectOutputDoubleToMatchThisPredicate.test(object.value));
}
@ParameterizedTest
@MethodSource("floatTestInputs")
void floatRoundTrip(FloatTestInput floatTestInput) {
// Serialise an object to JSON and ensure its represented correctly
JSONWire inputWire = new JSONWire();
inputWire.getValueOut().object(new FloatDto(floatTestInput.inputValue));
String text = JSONWire.asText(inputWire);
assertEquals(
String.format("{\"value\":\"%s\"}", floatTestInput.expectedStringRepresentation),
text,
"Expected JSON representation where special values are quoted string literals"
);
// Deserialize back to an object, ensure that the special value is retained
JSONWire outputWire = JSONWire.from(text);
FloatDto object = outputWire.getValueIn().object(FloatDto.class);
Assertions.assertNotNull(object);
Assertions.assertTrue(floatTestInput.expectOutputFloatToMatchThisPredicate.test(object.value));
}
@ParameterizedTest
@MethodSource("largeFiniteFloatInputs")
void largeFiniteFloatSerialiseAsJsonNumber(float value) {
String json = toJson(value);
Assertions.assertFalse(json.startsWith("\""),
"Finite float " + value + " must serialise as a JSON number, not a quoted string literal");
}
@ParameterizedTest
@MethodSource("largeFiniteDoubleInputs")
void largeFiniteDoubleSerialiseAsJsonNumber(double value) {
String json = toJson(value);
Assertions.assertFalse(json.startsWith("\""),
"Finite double " + value + " must serialise as a JSON number, not a quoted string literal");
}
private static Stream<Float> largeFiniteFloatInputs() {
return Stream.of(5_000_000.0f, 1e7f, -5_000_000.0f, 1.23456789e10f);
}
private static Stream<Double> largeFiniteDoubleInputs() {
return Stream.of(1e15, 1e16, -5e15, 1.23456789e20);
}
private static Stream<DoubleTestInput> doubleTestInputs() {
return Stream.of(
new DoubleTestInput(Double.NaN, "NaN", Double::isNaN),
new DoubleTestInput(Double.NEGATIVE_INFINITY, "-Infinity", Double::isInfinite),
new DoubleTestInput(Double.POSITIVE_INFINITY, "Infinity", Double::isInfinite)
);
}
private static class DoubleTestInput {
private final double inputValue;
private final String expectedStringRepresentation;
private final DoublePredicate expectOutputDoubleToMatchThisPredicate;
private DoubleTestInput(double inputValue,
String expectedStringRepresentation,
DoublePredicate expectOutputDoubleToMatchThisPredicate) {
this.inputValue = inputValue;
this.expectedStringRepresentation = expectedStringRepresentation;
this.expectOutputDoubleToMatchThisPredicate = expectOutputDoubleToMatchThisPredicate;
}
@Override
public String toString() {
return "DoubleTestInput{" +
"value=" + inputValue +
", expectedRepresentation='" + expectedStringRepresentation + '\'' +
'}';
}
}
private static Stream<FloatTestInput> floatTestInputs() {
return Stream.of(
new FloatTestInput(Float.NaN, "NaN", Double::isNaN),
new FloatTestInput(Float.NEGATIVE_INFINITY, "-Infinity", Double::isInfinite),
new FloatTestInput(Float.POSITIVE_INFINITY, "Infinity", Double::isInfinite)
);
}
private static class FloatTestInput {
private final float inputValue;
private final String expectedStringRepresentation;
private final Predicate<Float> expectOutputFloatToMatchThisPredicate; // No dedicated FloatPredicate in JDK
private FloatTestInput(float inputValue,
String expectedStringRepresentation,
Predicate<Float> expectOutputFloatToMatchThisPredicate) {
this.inputValue = inputValue;
this.expectedStringRepresentation = expectedStringRepresentation;
this.expectOutputFloatToMatchThisPredicate = expectOutputFloatToMatchThisPredicate;
}
@Override
public String toString() {
return "FloatTestInput{" +
"value=" + inputValue +
", expectedRepresentation='" + expectedStringRepresentation + '\'' +
'}';
}
}
/**
* Convert the double value to its JSON string representation.
*/
private String toJson(double value) {
JSONWire jsonWire = new JSONWire();
jsonWire.getValueOut().object(value);
return JSONWire.asText(jsonWire);
}
/**
* Convert the float value to its JSON string representation.
*/
private String toJson(float value) {
JSONWire jsonWire = new JSONWire();
jsonWire.getValueOut().object(value);
return JSONWire.asText(jsonWire);
}
/**
* Simple DTO for testing double serialise/deserialize to/from JSON.
*/
private static class DoubleDto extends SelfDescribingMarshallable {
private final double value;
private DoubleDto(double value) {
this.value = value;
}
}
/**
* Simple DTO for testing float serialise/deserialize to/from JSON.
*/
private static class FloatDto extends SelfDescribingMarshallable {
private final float value;
private FloatDto(float value) {
this.value = value;
}
}
}