Is this a bug in NSIndexSet enumerateIndexesUsingBlock?
Asked Answered
F

2

6

In my unit testing I was looking at some boundary conditions and my tests kept failing. I tracked it back to enumerating through an index set when its indexes extend all the way to NSNotFound-1 (the maximum legal value per the documentation).

Using this test code:

// Create an index set with NSNotFound-5, NSNotFound-4, NSNotFound-3, 
// NSNotFound-2 and NSNotFound-1
NSIndexSet *testSet = [NSIndexSet indexSetWithIndexesInRange:
    NSMakeRange( NSNotFound - 5, 5 )];
NSLog( @"Index set with %lu entries: %@", (unsigned long) testSet.count, testSet );
NSLog( @"NSNotFound is %lu and NSNotFound-1 is %lu", NSNotFound, NSNotFound - 1 );
__block int count = 0;
[testSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
    NSLog( @"- %lu", (unsigned long) idx );
    ++count;
}];
NSLog( @"The count is %d", count );

In the log output I get:

Index set with 5 entries: <NSIndexSet: 0x10057f890>[number of indexes: 5 (in 1 ranges), indexes: (9223372036854775802-9223372036854775806)]  
NSNotFound is 9223372036854775807 and NSNotFound-1 is 9223372036854775806  
- 9223372036854775802  
- 9223372036854775803  
- 9223372036854775804  
- 9223372036854775805  
The count is 4  

I tried this on my Mac and on the iOS simulator and get the same results (other than the actual values of NSNotFound, depending on 32 bit or 64 bit).

This made me think maybe I was reading the documentation wrong. Am I doing something wrong or is this an Apple bug?

Faceharden answered 17/5, 2014 at 15:13 Comment(7)
That it an interesting question. +1Doloroso
That really looks like a bug in enumerateIndexesWithOptions.Loralorain
Does it work if you start the range at NSNotFound - 6 (and keep the length 5)?Agrology
Yes, the count comes out 5 as expected.Faceharden
I think this is actually a broader bug in NSIndexSet; all its enumeration methods have the same issue. Certainly worth filing a bug report. That said, I'm curious how this came up, and if it's likely to affect real-world code—I'm pretty sure you won't have much luck allocating an array of 9223372036854775807 objects. :-)Ragan
@Sean D. Maybe if they are really really tiny objects? Nano computing? No, like I said, it was while unit testing. I try to test "boundary" conditions since these are the most likely to fail. So I put in nil, zero length, maximum length, etc., and make sure those cases work. If those all work, and at least one "normal" case works, I am pretty confident in the code --- apparently Apple does not do the same but my testing of NSIndexSet's that do not go all the way to (NSNotFound - 1) seem to work properly.Faceharden
My guess is that there's another constant at NSNotFound-1 that is being ignored by NSIndexSet which is not mentioned in the documentation.Blurb
F
0

Well it looks like I have confirmation that it is/was a bug. I put in a bug report and heard from Apple that it is fixed in the latest OS X Yosemite Developer Preview and Xcode Preview. I downloaded it and it seemed to work as expected from the documentation.

I suspect they had to change one line of code so asked if they would be patching the current or previous versions of Xcode but I have not heard and I am not holding my breath.

Faceharden answered 28/8, 2014 at 15:55 Comment(0)
T
0

It's not a bug. The value you set is out of valied values. "The NSIndexSet class represents an immutable collection of unique unsigned integers, known as indexes because of the way they are used. This collection is referred to as an index set. Indexes must be in the range 0 .. NSNotFound - 1." Here's link!

Tape answered 9/6, 2014 at 3:54 Comment(2)
I have read the documentation and my indexes are: NSNotFound-5, NSNotFound-4, NSNotFound-3, NSNotFound-2 and NSNotFound-1, all are > 0 and <= NSNotFound-1. The NSIndexSet is created correctly, as shown by the NSLog() output, but the enumeration does not make it to the last index. If I do [NSIndexSet indexSetWithIndexesInRange: NSMakeRange( NSNotFound - 5, 6)] it generates the error *** -[NSIndexSet initWithIndexesInRange:]: Range {9223372036854775802, 6} exceeds maximum index value of NSNotFound - 1. I am not exceeding the maximum value, I'm pretty sure the enumeration methods are broken.Faceharden
Sorry, I misunderstood what you mean at the beginning. I've tested that code, I think that is about the boundary value, It's a bug.Tape
F
0

Well it looks like I have confirmation that it is/was a bug. I put in a bug report and heard from Apple that it is fixed in the latest OS X Yosemite Developer Preview and Xcode Preview. I downloaded it and it seemed to work as expected from the documentation.

I suspect they had to change one line of code so asked if they would be patching the current or previous versions of Xcode but I have not heard and I am not holding my breath.

Faceharden answered 28/8, 2014 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.