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?

nobody
  • 19,814
  • 17
  • 56
  • 77
LavaSlider
  • 2,494
  • 18
  • 29
  • That it an interesting question. +1 – trojanfoe May 17 '14 at 15:32
  • That really looks like a bug in `enumerateIndexesWithOptions`. – Martin R May 17 '14 at 15:51
  • Does it work if you start the range at `NSNotFound - 6` (and keep the length 5)? – nobody May 17 '14 at 17:03
  • Yes, the count comes out 5 as expected. – LavaSlider May 17 '14 at 21:01
  • 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. :-) – Siobhán May 21 '14 at 15:19
  • @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. – LavaSlider May 22 '14 at 19:10
  • My guess is that there's another constant at NSNotFound-1 that is being ignored by NSIndexSet which is not mentioned in the documentation. – harrisg Jun 05 '14 at 18:45

2 Answers2

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!

user2523232
  • 309
  • 1
  • 9
  • 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. – LavaSlider Jun 09 '14 at 16:05
  • 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. – user2523232 Jun 10 '14 at 03:43
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.

LavaSlider
  • 2,494
  • 18
  • 29