Skip to content

Commit 3483dfa

Browse files
NickGerlemanmeta-codesync[bot]
authored andcommitted
Round debug float output to 4 decimal places (#55879)
Summary: Pull Request resolved: #55879 Float values in debug layout metrics output (used by Fantom test assertions) are subject to floating-point precision differences across platforms and compilers (e.g., `66.6667` vs `66.66666412353516`), causing flaky test comparisons. This changes `toString(const double&)` in `DebugStringConvertible.cpp` to format floats with 4 decimal places using `snprintf("%.4f")` and strip trailing zeros, replacing `double-conversion`'s `ToShortest()`. This is debug-only code (guarded by `#if RN_DEBUG_STRING_CONVERTIBLE`) so the precision change is safe for all consumers. The `double-conversion` dependency is also removed from the BUCK file since it is no longer used. Output examples: - `0.0` → `"0"` - `100.0` → `"100"` - `66.66666412353516` → `"66.6667"` - `1.5` → `"1.5"` - `33.333333` → `"33.3333"` Changelog: [Internal] Reviewed By: javache Differential Revision: D95041966 fbshipit-source-id: 4cce0c9ade73137d6a3d1fffd43905a1cf6d76ac
1 parent 53cd9ce commit 3483dfa

File tree

16 files changed

+119
-143
lines changed

16 files changed

+119
-143
lines changed

packages/react-native/Libraries/Animated/__tests__/Animated-itest.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ test('moving box by 50 points with offset 10', () => {
332332
// TODO(T232605345): The following line won't be necessary once race condition on Android is fixed.
333333
Fantom.runWorkLoop();
334334
expect(root.getRenderedOutput({props: ['transform']}).toJSX()).toEqual(
335-
<rn-view transform='[{"translateX": 60.000000}]' />,
335+
<rn-view transform='[{"translateX": 60}]' />,
336336
);
337337

338338
expect(finishValue?.finished).toBe(true);
@@ -579,7 +579,7 @@ test('animate layout props', () => {
579579
}
580580

581581
expect(root.getRenderedOutput({props: ['height']}).toJSX()).toEqual(
582-
<rn-view height="100.000000" />,
582+
<rn-view height="100" />,
583583
);
584584
});
585585

packages/react-native/Libraries/Animated/__tests__/AnimatedBackend-itest.js

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ test('animate layout props', () => {
117117
// TODO: getFabricUpdateProps is not working with the cloneMutliple method
118118
// expect(Fantom.unstable_getFabricUpdateProps(viewElement).height).toBe(100);
119119
expect(root.getRenderedOutput({props: ['height']}).toJSX()).toEqual(
120-
<rn-view height="50.000000" />,
120+
<rn-view height="50" />,
121121
);
122122

123123
Fantom.unstable_produceFramesForDuration(100);
@@ -128,7 +128,7 @@ test('animate layout props', () => {
128128
});
129129

130130
expect(root.getRenderedOutput({props: ['height']}).toJSX()).toEqual(
131-
<rn-view height="100.000000" />,
131+
<rn-view height="100" />,
132132
);
133133
});
134134

@@ -174,7 +174,7 @@ test('animate layout props and rerender', () => {
174174

175175
Fantom.unstable_produceFramesForDuration(500);
176176
expect(root.getRenderedOutput({props: ['height', 'width']}).toJSX()).toEqual(
177-
<rn-view height="50.000000" width="100.000000" />,
177+
<rn-view height="50" width="100" />,
178178
);
179179

180180
Fantom.runTask(() => {
@@ -184,7 +184,7 @@ test('animate layout props and rerender', () => {
184184
// TODO: getFabricUpdateProps is not working with the cloneMutliple method
185185
// expect(Fantom.unstable_getFabricUpdateProps(viewElement).height).toBe(50);
186186
expect(root.getRenderedOutput({props: ['height', 'width']}).toJSX()).toEqual(
187-
<rn-view height="50.000000" width="200.000000" />,
187+
<rn-view height="50" width="200" />,
188188
);
189189

190190
Fantom.unstable_produceFramesForDuration(500);
@@ -195,15 +195,15 @@ test('animate layout props and rerender', () => {
195195
});
196196

197197
expect(root.getRenderedOutput({props: ['height', 'width']}).toJSX()).toEqual(
198-
<rn-view height="100.000000" width="200.000000" />,
198+
<rn-view height="100" width="200" />,
199199
);
200200

201201
Fantom.runTask(() => {
202202
_setWidth(300);
203203
});
204204

205205
expect(root.getRenderedOutput({props: ['height', 'width']}).toJSX()).toEqual(
206-
<rn-view height="100.000000" width="300.000000" />,
206+
<rn-view height="100" width="300" />,
207207
);
208208
});
209209

@@ -250,9 +250,9 @@ test('animate non-layout props and rerender', () => {
250250

251251
Fantom.unstable_produceFramesForDuration(500);
252252

253-
// TODO: rendered output should be <rn-view opacity="0,5" width="100.000000" /> at this point, but synchronous updates are not captured by fantom
253+
// TODO: rendered output should be <rn-view opacity="0,5" width="100" /> at this point, but synchronous updates are not captured by fantom
254254
expect(root.getRenderedOutput({props: ['width']}).toJSX()).toEqual(
255-
<rn-view width="100.000000" />,
255+
<rn-view width="100" />,
256256
);
257257

258258
expect(
@@ -265,7 +265,7 @@ test('animate non-layout props and rerender', () => {
265265
});
266266

267267
expect(root.getRenderedOutput({props: ['opacity', 'width']}).toJSX()).toEqual(
268-
<rn-view opacity="0.25" width="150.000000" />,
268+
<rn-view opacity="0.25" width="150" />,
269269
);
270270

271271
Fantom.runTask(() => {
@@ -275,7 +275,7 @@ test('animate non-layout props and rerender', () => {
275275
// TODO: getFabricUpdateProps is not working with the cloneMutliple method
276276
// expect(Fantom.unstable_getFabricUpdateProps(viewElement).height).toBe(50);
277277
expect(root.getRenderedOutput({props: ['opacity', 'width']}).toJSX()).toEqual(
278-
<rn-view opacity="0.25" width="200.000000" />,
278+
<rn-view opacity="0.25" width="200" />,
279279
);
280280

281281
Fantom.unstable_produceFramesForDuration(500);
@@ -287,7 +287,7 @@ test('animate non-layout props and rerender', () => {
287287

288288
// TODO: T246961305 rendered output should be <rn-view opacity="1" /> at this point
289289
expect(root.getRenderedOutput({props: ['width']}).toJSX()).toEqual(
290-
<rn-view width="200.000000" />,
290+
<rn-view width="200" />,
291291
);
292292

293293
expect(Fantom.unstable_getDirectManipulationProps(viewElement).opacity).toBe(
@@ -300,7 +300,7 @@ test('animate non-layout props and rerender', () => {
300300
});
301301

302302
expect(root.getRenderedOutput({props: ['opacity', 'width']}).toJSX()).toEqual(
303-
<rn-view opacity="0.5" width="300.000000" />,
303+
<rn-view opacity="0.5" width="300" />,
304304
);
305305
});
306306

@@ -373,9 +373,9 @@ test('animate layout props and rerender in many components', () => {
373373

374374
Fantom.unstable_produceFramesForDuration(500);
375375
expect(root.getRenderedOutput({props: ['height', 'width']}).toJSX()).toEqual(
376-
<rn-view height="50.000000" width="100.000000">
376+
<rn-view height="50" width="100">
377377
{Array.from({length: N}, (_, i) => (
378-
<rn-view key={i} height="50.000000" width="100.000000" />
378+
<rn-view key={i} height="50" width="100" />
379379
))}
380380
</rn-view>,
381381
);
@@ -392,9 +392,9 @@ test('animate layout props and rerender in many components', () => {
392392
// TODO: getFabricUpdateProps is not working with the cloneMutliple method
393393
// expect(Fantom.unstable_getFabricUpdateProps(viewElement).height).toBe(50);
394394
expect(root.getRenderedOutput({props: ['height', 'width']}).toJSX()).toEqual(
395-
<rn-view height="50.000000" width="200.000000">
395+
<rn-view height="50" width="200">
396396
{Array.from({length: N}, (_, i) => (
397-
<rn-view key={i} height="50.000000" width="100.000000" />
397+
<rn-view key={i} height="50" width="100" />
398398
))}
399399
</rn-view>,
400400
);
@@ -466,7 +466,7 @@ test('animate width, height and opacity at once', () => {
466466

467467
expect(
468468
root.getRenderedOutput({props: ['width', 'height', 'opacity']}).toJSX(),
469-
).toEqual(<rn-view height="200.000000" opacity="0.5" width="200.000000" />);
469+
).toEqual(<rn-view height="200" opacity="0.5" width="200" />);
470470
});
471471

472472
test('animate width with memo and rerender (js sync test)', () => {
@@ -532,7 +532,7 @@ test('animate width with memo and rerender (js sync test)', () => {
532532
});
533533

534534
expect(root.getRenderedOutput({props: ['width', 'height']}).toJSX()).toEqual(
535-
<rn-view height="100.000000" width="100.000000" />,
535+
<rn-view height="100" width="100" />,
536536
);
537537

538538
Fantom.unstable_produceFramesForDuration(1000);
@@ -543,7 +543,7 @@ test('animate width with memo and rerender (js sync test)', () => {
543543
});
544544

545545
expect(root.getRenderedOutput({props: ['width']}).toJSX()).toEqual(
546-
<rn-view width="200.000000" />,
546+
<rn-view width="200" />,
547547
);
548548

549549
// Trigger rerender after animation completes to see if animation state gets overwritten
@@ -552,6 +552,6 @@ test('animate width with memo and rerender (js sync test)', () => {
552552
});
553553

554554
expect(root.getRenderedOutput({props: ['width']}).toJSX()).toEqual(
555-
<rn-view width="200.000000" />,
555+
<rn-view width="200" />,
556556
);
557557
});

packages/react-native/Libraries/Components/ActivityIndicator/__tests__/ActivityIndicator-itest.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ describe('<ActivityIndicator>', () => {
2828
});
2929

3030
expect(root.getRenderedOutput().toJSX()).toEqual(
31-
<rn-androidProgressBar height="20.000000" width="20.000000" />,
31+
<rn-androidProgressBar height="20" width="20" />,
3232
);
3333
});
3434

@@ -40,7 +40,7 @@ describe('<ActivityIndicator>', () => {
4040
});
4141

4242
expect(root.getRenderedOutput().toJSX()).toEqual(
43-
<rn-androidProgressBar height="20.000000" width="20.000000" />,
43+
<rn-androidProgressBar height="20" width="20" />,
4444
);
4545
});
4646

@@ -52,7 +52,7 @@ describe('<ActivityIndicator>', () => {
5252
});
5353

5454
expect(root.getRenderedOutput().toJSX()).toEqual(
55-
<rn-androidProgressBar height="36.000000" width="36.000000" />,
55+
<rn-androidProgressBar height="36" width="36" />,
5656
);
5757
});
5858

@@ -64,7 +64,7 @@ describe('<ActivityIndicator>', () => {
6464
});
6565

6666
expect(root.getRenderedOutput().toJSX()).toEqual(
67-
<rn-androidProgressBar height="48.000000" width="48.000000" />,
67+
<rn-androidProgressBar height="48" width="48" />,
6868
);
6969
});
7070
});
@@ -80,7 +80,7 @@ describe('<ActivityIndicator>', () => {
8080
// Color is a native prop not serialized as a view attribute,
8181
// but the component still renders correctly
8282
expect(root.getRenderedOutput().toJSX()).toEqual(
83-
<rn-androidProgressBar height="20.000000" width="20.000000" />,
83+
<rn-androidProgressBar height="20" width="20" />,
8484
);
8585
});
8686
});
@@ -95,7 +95,7 @@ describe('<ActivityIndicator>', () => {
9595

9696
// Component renders normally when animating (default)
9797
expect(root.getRenderedOutput().toJSX()).toEqual(
98-
<rn-androidProgressBar height="20.000000" width="20.000000" />,
98+
<rn-androidProgressBar height="20" width="20" />,
9999
);
100100
});
101101

@@ -108,7 +108,7 @@ describe('<ActivityIndicator>', () => {
108108

109109
// Component still renders when not animating
110110
expect(root.getRenderedOutput().toJSX()).toEqual(
111-
<rn-androidProgressBar height="20.000000" width="20.000000" />,
111+
<rn-androidProgressBar height="20" width="20" />,
112112
);
113113
});
114114
});

packages/react-native/Libraries/Components/Pressable/__tests__/Pressable-itest.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ describe('<Pressable>', () => {
4848
accessible="true"
4949
accessibilityState="{disabled:false,selected:false,checked:None,busy:false,expanded:null}"
5050
backgroundColor="rgba(0, 0, 255, 1)"
51-
borderWidth="3.000000"
52-
height="50.000000"
51+
borderWidth="3"
52+
height="50"
5353
opacity="40"
54-
width="100.000000"
54+
width="100"
5555
/>,
5656
);
5757
});
@@ -148,8 +148,8 @@ describe('<Pressable>', () => {
148148
<rn-paragraph
149149
allowFontScaling="true"
150150
ellipsizeMode="tail"
151-
fontSize="NaN"
152-
fontSizeMultiplier="NaN"
151+
fontSize="nan"
152+
fontSizeMultiplier="nan"
153153
foregroundColor="rgba(0, 0, 0, 0)"
154154
overflow="hidden">
155155
the quick brown fox

packages/react-native/Libraries/Components/Touchable/__tests__/TouchableHighlight-itest.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ describe('<TouchableHighlight>', () => {
7777
).toEqual(
7878
<rn-view
7979
backgroundColor="rgba(0, 0, 255, 1)"
80-
height="50.000000"
81-
width="100.000000"
80+
height="50"
81+
width="100"
8282
/>,
8383
);
8484
});
@@ -130,7 +130,7 @@ describe('<TouchableHighlight>', () => {
130130

131131
expect(root.getRenderedOutput({props: ['opacity']}).toJSX()).toEqual(
132132
<rn-view>
133-
<rn-view opacity="0.8500000238418579" />
133+
<rn-view opacity="0.85" />
134134
</rn-view>,
135135
);
136136
});

packages/react-native/Libraries/Components/Touchable/__tests__/TouchableOpacity-itest.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ describe('<TouchableOpacity>', () => {
6161
).toEqual(
6262
<rn-view
6363
backgroundColor="rgba(0, 0, 255, 1)"
64-
height="50.000000"
65-
width="100.000000"
64+
height="50"
65+
width="100"
6666
/>,
6767
);
6868
});

packages/react-native/Libraries/Components/View/__tests__/View-itest.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ describe('<View>', () => {
4343
).toEqual(
4444
<rn-view
4545
layoutMetrics-frame="{x:0,y:0,width:20,height:50}"
46-
height="50.000000%"
46+
height="50%"
4747
layoutMetrics-borderWidth="{top:0,right:0,bottom:0,left:0}"
4848
layoutMetrics-contentInsets="{top:0,right:0,bottom:0,left:0}"
4949
layoutMetrics-displayType="Flex"
5050
layoutMetrics-layoutDirection="LeftToRight"
5151
layoutMetrics-overflowInset="{top:0,right:-0,bottom:-0,left:0}"
5252
layoutMetrics-pointScaleFactor="3"
53-
width="20.000000%"
53+
width="20%"
5454
/>,
5555
);
5656
});
@@ -69,14 +69,14 @@ describe('<View>', () => {
6969
).toEqual(
7070
<rn-view
7171
layoutMetrics-frame="{x:0,y:0,width:5,height:10}"
72-
height="10.000000"
72+
height="10"
7373
layoutMetrics-borderWidth="{top:0,right:0,bottom:0,left:0}"
7474
layoutMetrics-contentInsets="{top:0,right:0,bottom:0,left:0}"
7575
layoutMetrics-displayType="Flex"
7676
layoutMetrics-layoutDirection="LeftToRight"
7777
layoutMetrics-overflowInset="{top:0,right:-0,bottom:-0,left:0}"
7878
layoutMetrics-pointScaleFactor="3"
79-
width="5.000000"
79+
width="5"
8080
/>,
8181
);
8282
});
@@ -134,15 +134,15 @@ describe('<View>', () => {
134134
).toEqual(
135135
<rn-view
136136
layoutMetrics-frame="{x:50,y:50,width:5,height:10}"
137-
height="10.000000"
137+
height="10"
138138
layoutMetrics-borderWidth="{top:0,right:0,bottom:0,left:0}"
139139
layoutMetrics-contentInsets="{top:0,right:0,bottom:0,left:0}"
140140
layoutMetrics-displayType="Flex"
141141
layoutMetrics-layoutDirection="LeftToRight"
142142
layoutMetrics-overflowInset="{top:0,right:-0,bottom:-0,left:0}"
143143
layoutMetrics-pointScaleFactor="3"
144-
margin="50.000000%"
145-
width="5.000000"
144+
margin="50%"
145+
width="5"
146146
/>,
147147
);
148148
});
@@ -166,15 +166,15 @@ describe('<View>', () => {
166166
).toEqual(
167167
<rn-view
168168
layoutMetrics-frame="{x:5,y:5,width:5,height:10}"
169-
height="10.000000"
169+
height="10"
170170
layoutMetrics-borderWidth="{top:0,right:0,bottom:0,left:0}"
171171
layoutMetrics-contentInsets="{top:0,right:0,bottom:0,left:0}"
172172
layoutMetrics-displayType="Flex"
173173
layoutMetrics-layoutDirection="LeftToRight"
174174
layoutMetrics-overflowInset="{top:0,right:-0,bottom:-0,left:0}"
175175
layoutMetrics-pointScaleFactor="3"
176-
margin="5.000000"
177-
width="5.000000"
176+
margin="5"
177+
width="5"
178178
/>,
179179
);
180180
});
@@ -190,7 +190,7 @@ describe('<View>', () => {
190190

191191
expect(
192192
root.getRenderedOutput({props: ['transform']}).toJSX(),
193-
).toEqual(<rn-view transform='[{"translateX": 10.000000}]' />);
193+
).toEqual(<rn-view transform='[{"translateX": 10}]' />);
194194
});
195195

196196
[

0 commit comments

Comments
 (0)