From bc4132dba7279fdf8177aaa63687642d50ac11b6 Mon Sep 17 00:00:00 2001 From: Yury Bogdanov Date: Mon, 18 Dec 2017 11:45:31 -0800 Subject: [PATCH] Negative size assertion Summary: Assertions for item's size added to prevent negative values return from IGListAdapter Issue fixed: #977 - [x] All tests pass. Demo project builds and runs. - [x] I added tests, an experiment, or detailed why my change isn't tested. - [ ] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes. - [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md) Closes https://github.com/Instagram/IGListKit/pull/992 Reviewed By: ryanolsonk Differential Revision: D6272307 Pulled By: rnystrom fbshipit-source-id: 844affd914329e0ca04597ada2952f1a077897af --- .../Internal/IGListAdapter+UICollectionView.m | 7 +++- Tests/IGListAdapterTests.m | 37 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/Source/Internal/IGListAdapter+UICollectionView.m b/Source/Internal/IGListAdapter+UICollectionView.m index 84d0973f..c6b97d37 100644 --- a/Source/Internal/IGListAdapter+UICollectionView.m +++ b/Source/Internal/IGListAdapter+UICollectionView.m @@ -176,7 +176,12 @@ - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); - return [self sizeForItemAtIndexPath:indexPath]; + + CGSize size = [self sizeForItemAtIndexPath:indexPath]; + IGAssert(!isnan(size.height), @"IGListAdapter returned NaN height = %f for item at indexPath <%@>", size.height, indexPath); + IGAssert(!isnan(size.width), @"IGListAdapter returned NaN width = %f for item at indexPath <%@>", size.width, indexPath); + + return size; } - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { diff --git a/Tests/IGListAdapterTests.m b/Tests/IGListAdapterTests.m index f80655d1..7ef91479 100644 --- a/Tests/IGListAdapterTests.m +++ b/Tests/IGListAdapterTests.m @@ -18,6 +18,7 @@ #import "IGListAdapterInternal.h" #import "IGListTestAdapterDataSource.h" #import "IGListTestAdapterHorizontalDataSource.h" +#import "IGListTestOffsettingLayout.h" #import "IGListTestSection.h" #import "IGTestSupplementarySource.h" #import "IGTestNibSupplementaryView.h" @@ -1327,6 +1328,42 @@ XCTAssertEqual(size.height, 0.0); } +- (void)test_whenSectionControllerReturnsNANHeight_thatAssertionFires { + self.adapter.collectionView.collectionViewLayout = [IGListTestOffsettingLayout new]; + self.dataSource.objects = @[@1]; + [self.adapter reloadDataWithCompletion:nil]; + + IGListTestSection *section = [self.adapter sectionControllerForObject:self.dataSource.objects[0]]; + section.size = CGSizeMake(NAN, 1); + + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; + XCTAssertThrows([self.adapter collectionView:self.collectionView layout:self.collectionView.collectionViewLayout sizeForItemAtIndexPath:indexPath]); +} + +- (void)test_whenSectionControllerReturnsNANWidth_thatAssertionFires { + self.adapter.collectionView.collectionViewLayout = [IGListTestOffsettingLayout new]; + self.dataSource.objects = @[@1]; + [self.adapter reloadDataWithCompletion:nil]; + + IGListTestSection *section = [self.adapter sectionControllerForObject:self.dataSource.objects[0]]; + section.size = CGSizeMake(1, NAN); + + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; + XCTAssertThrows([self.adapter collectionView:self.collectionView layout:self.collectionView.collectionViewLayout sizeForItemAtIndexPath:indexPath]); +} + +- (void)test_whenSectionControllerReturnsNANWidthNANHeight_thatAssertionFires { + self.adapter.collectionView.collectionViewLayout = [IGListTestOffsettingLayout new]; + self.dataSource.objects = @[@1]; + [self.adapter reloadDataWithCompletion:nil]; + + IGListTestSection *section = [self.adapter sectionControllerForObject:self.dataSource.objects[0]]; + section.size = CGSizeMake(NAN, NAN); + + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; + XCTAssertThrows([self.adapter collectionView:self.collectionView layout:self.collectionView.collectionViewLayout sizeForItemAtIndexPath:indexPath]); +} + - (void)test_whenSupplementarySourceReturnsNegativeSize_thatAdapterReturnsZero { self.dataSource.objects = @[@1]; [self.adapter reloadDataWithCompletion:nil];