Skip to content

Commit a2fc0e1

Browse files
Antonio Corradofacebook-github-bot
Antonio Corrado
authored andcommitted
Size Range comparison with epsilon
Summary: In some cases size range comparison can assert because of rounding issues with floating point numbers. By adding a comparison with an epsilon we can reduce the cases for false positives. Reviewed By: Andrey-Mishanin Differential Revision: D8874248 fbshipit-source-id: 1e6949b5e26c734241401e001bd1a7d7e5523954
1 parent 2f09941 commit a2fc0e1

File tree

3 files changed

+66
-4
lines changed

3 files changed

+66
-4
lines changed

ComponentKit/Core/CKComponent.mm

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,10 @@ - (CKComponentLayout)layoutThatFits:(CKSizeRange)constrainedSize parentSize:(CGS
296296
CKAssert(layout.component == self, @"Layout computed by %@ should return self as component, but returned %@",
297297
[self class], [layout.component class]);
298298
CKSizeRange resolvedRange __attribute__((unused)) = constrainedSize.intersect(_size.resolve(parentSize));
299-
CKAssertWithCategory(layout.size.width <= resolvedRange.max.width
300-
&& layout.size.width >= resolvedRange.min.width
301-
&& layout.size.height <= resolvedRange.max.height
302-
&& layout.size.height >= resolvedRange.min.height,
299+
CKAssertWithCategory(CKIsGreaterThanOrEqualWithTolerance(resolvedRange.max.width, layout.size.width)
300+
&& CKIsGreaterThanOrEqualWithTolerance(layout.size.width, resolvedRange.min.width)
301+
&& CKIsGreaterThanOrEqualWithTolerance(resolvedRange.max.height,layout.size.height)
302+
&& CKIsGreaterThanOrEqualWithTolerance(layout.size.height,resolvedRange.min.height),
303303
NSStringFromClass([self class]),
304304
@"Computed size %@ for %@ does not fall within constrained size %@\n%@",
305305
NSStringFromCGSize(layout.size), [self class], resolvedRange.description(),

ComponentKit/Utilities/CKInternalHelpers.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ static inline BOOL CKFloatsEqual(const CGFloat a, const CGFloat b) noexcept {
3131
return fabs(a - b) < 0.0001f;
3232
}
3333

34+
static inline bool CKIsGreaterThanOrEqualWithTolerance(CGFloat a,CGFloat b) {
35+
return a > b || CKFloatsEqual(a, b);
36+
}
37+
3438
static inline CGFloat CKRoundValueToPixelGrid(CGFloat value, const BOOL forceCeil,
3539
const BOOL forceFloor) noexcept
3640
{

ComponentKitTests/CKSizeRangeTests.mm

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2014-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*
9+
*/
10+
11+
#import <XCTest/XCTest.h>
12+
#import <ComponentKit/CKInternalHelpers.h>
13+
#import <ComponentKit/CKSizeRange.h>
14+
15+
@interface CKSizeRangeTests : XCTestCase
16+
17+
@end
18+
19+
@implementation CKSizeRangeTests
20+
21+
static bool verifySizeRange(CKSizeRange &sz,CGSize &size) {
22+
return CKIsGreaterThanOrEqualWithTolerance(sz.max.width, size.width)
23+
&& CKIsGreaterThanOrEqualWithTolerance(size.width, sz.min.width)
24+
&& CKIsGreaterThanOrEqualWithTolerance(sz.max.height,size.height)
25+
&& CKIsGreaterThanOrEqualWithTolerance(size.height,sz.min.height);
26+
}
27+
28+
- (void)testExactMatch {
29+
CKSizeRange sz(CGSizeMake(400, 400), CGSizeMake(400, 400));
30+
CGSize s = CGSizeMake(400, 400);
31+
XCTAssert(verifySizeRange(sz, s));
32+
}
33+
34+
- (void)testRangeMatch {
35+
CKSizeRange sz(CGSizeMake(0, 0), CGSizeMake(INFINITY, INFINITY));
36+
CGSize s = CGSizeMake(400, 400);
37+
XCTAssert(verifySizeRange(sz, s));
38+
}
39+
40+
- (void)testNaNMatch {
41+
CKSizeRange sz(CGSizeMake(NAN, NAN), CGSizeMake(NAN, NAN));
42+
CGSize s = CGSizeMake(NAN, NAN);
43+
XCTAssert(verifySizeRange(sz, s));
44+
}
45+
46+
- (void)testVerySmallDifferenceMatch {
47+
CKSizeRange sz(CGSizeMake(374.99999999999994, 400), CGSizeMake(374.99999999999994, 400));
48+
CGSize s = CGSizeMake(375, 400);
49+
XCTAssert(verifySizeRange(sz, s));
50+
}
51+
52+
- (void)testVerySmallDifferenceRangeMatch {
53+
CKSizeRange sz(CGSizeMake(0, 380), CGSizeMake(INFINITY, 400));
54+
CGSize s = CGSizeMake(400, 379.99999999999994);
55+
XCTAssert(verifySizeRange(sz, s));
56+
}
57+
58+
@end

0 commit comments

Comments
 (0)