PageRenderTime 152ms CodeModel.GetById 11ms app.highlight 134ms RepoModel.GetById 1ms app.codeStats 1ms

/core/externals/google-toolbox-for-mac/UnitTesting/GTMNSObject+BindingUnitTesting.m

http://macfuse.googlecode.com/
Objective C | 577 lines | 441 code | 64 blank | 72 comment | 71 complexity | b1a2f6e9e46e6b4d35e41acac1f9c411 MD5 | raw file
  1//
  2//  GTMNSObject+BindingUnitTesting.m
  3//  
  4//  An informal protocol for doing advanced binding unittesting with objects.
  5//
  6//  Copyright 2006-2008 Google Inc.
  7//
  8//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  9//  use this file except in compliance with the License.  You may obtain a copy
 10//  of the License at
 11// 
 12//  http://www.apache.org/licenses/LICENSE-2.0
 13// 
 14//  Unless required by applicable law or agreed to in writing, software
 15//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 16//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 17//  License for the specific language governing permissions and limitations under
 18//  the License.
 19//
 20
 21#import <AppKit/AppKit.h>
 22#import "GTMDefines.h"
 23#import "GTMNSObject+BindingUnitTesting.h"
 24#import "GTMSystemVersion.h"
 25
 26BOOL GTMDoExposedBindingsFunctionCorrectly(NSObject *object, 
 27                                           NSArray **errors) {
 28  NSMutableArray *errorArray = [NSMutableArray array];
 29  if (errors) {
 30    *errors = nil;
 31  }
 32  NSArray *bindings = [object exposedBindings];
 33  if ([bindings count]) {
 34    NSArray *bindingsToIgnore = [object gtm_unitTestExposedBindingsToIgnore];
 35    NSString *bindingKey;
 36    GTM_FOREACH_OBJECT(bindingKey, bindings) {
 37      if (![bindingsToIgnore containsObject:bindingKey]) {
 38        Class theClass = [object valueClassForBinding:bindingKey];
 39        if (!theClass) {
 40          NSString *error 
 41            = [NSString stringWithFormat:@"%@ should have valueClassForBinding '%@'",
 42               object, bindingKey];
 43          [errorArray addObject:error];
 44          continue;
 45        }
 46        @try {
 47          @try {
 48            [object valueForKey:bindingKey];
 49          }
 50          @catch (NSException *e) {
 51            _GTMDevLog(@"%@ is not key value coding compliant for key %@", 
 52                       object, bindingKey);
 53            continue;
 54          }  // COV_NF_LINE - compiler bug
 55          NSArray *testValues 
 56            = [object gtm_unitTestExposedBindingsTestValues:bindingKey];
 57          GTMBindingUnitTestData *testData;
 58          GTM_FOREACH_OBJECT(testData, testValues) {
 59            id valueToSet = [testData valueToSet];
 60            [object setValue:valueToSet forKey:bindingKey];
 61            id valueReceived = [object valueForKey:bindingKey];
 62            id desiredValue = [testData expectedValue];
 63            if (![desiredValue gtm_unitTestIsEqualTo:valueReceived]) {
 64              NSString *error 
 65                = [NSString stringWithFormat:@"%@ unequal to expected %@ for binding '%@'",
 66                   valueReceived, desiredValue, bindingKey];
 67              [errorArray addObject:error];
 68              continue;
 69            }
 70          }
 71        }
 72        @catch(NSException *e) {
 73          NSString *error 
 74            = [NSString stringWithFormat:@"%@:%@-> Binding %@", 
 75               [e name], [e reason], bindingKey];
 76          [errorArray addObject:error];
 77        }  // COV_NF_LINE - compiler bug
 78      }
 79    }
 80  } else {
 81    NSString *error = 
 82      [NSString stringWithFormat:@"%@ does not have any exposed bindings",
 83       object];
 84    [errorArray addObject:error];
 85  }
 86  if (errors) {
 87    *errors = errorArray;
 88  }
 89  return [errorArray count] == 0;
 90}
 91
 92@implementation GTMBindingUnitTestData
 93+ (id)testWithIdentityValue:(id)value {
 94  return [self testWithValue:value expecting:value];
 95}
 96
 97+ (id)testWithValue:(id)value expecting:(id)expecting {
 98  return [[[self alloc] initWithValue:value expecting:expecting] autorelease];
 99}
100
101- (id)initWithValue:(id)value expecting:(id)expecting {
102  if ((self = [super init])) {
103    valueToSet_ = [value retain];
104    expectedValue_ = [expecting retain];
105  }
106  return self;
107}
108
109- (BOOL)isEqual:(id)object {
110  BOOL isEqual = [object isMemberOfClass:[self class]];
111  if (isEqual) {
112    id objValue = [object valueToSet];
113    id objExpect = [object expectedValue];
114    isEqual = (((valueToSet_ == objValue) || ([valueToSet_ isEqual:objValue]))
115      && ((expectedValue_ == objExpect) || ([expectedValue_ isEqual:objExpect])));
116  }
117  return isEqual;
118}
119
120- (NSUInteger)hash {
121  return [valueToSet_ hash] + [expectedValue_ hash];
122}
123
124- (void)dealloc {
125  [valueToSet_ release];
126  [expectedValue_ release];
127  [super dealloc];
128}
129
130- (id)valueToSet {
131  return valueToSet_;
132}
133
134- (id)expectedValue {
135  return expectedValue_;
136}
137@end
138
139@implementation NSObject (GTMBindingUnitTestingAdditions)
140
141- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
142  NSMutableArray *array = [NSMutableArray arrayWithObject:NSValueBinding];
143  if ([[self exposedBindings] containsObject:NSFontBinding]) {
144    NSString *fontBindings[] = { NSFontBoldBinding, NSFontFamilyNameBinding, 
145    NSFontItalicBinding, NSFontNameBinding, NSFontSizeBinding };
146    for (size_t i = 0; i < sizeof(fontBindings) / sizeof(NSString*); ++i) {
147      [array addObject:fontBindings[i]];
148    }
149  }
150  return array;
151}
152
153- (NSMutableArray*)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
154  
155  NSMutableArray *array = [NSMutableArray array];
156  id value = [self valueForKey:binding];
157  
158  // Always test identity if possible
159  if (value) {
160    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
161  }
162  
163  // Now some default test values for a variety of bindings to make
164  // sure that we cover all the bases and save other people writing lots of
165  // duplicate test code.
166  
167  // If anybody can think of more to add, please go nuts.
168  if ([binding isEqualToString:NSAlignmentBinding]) {
169    value = [NSNumber numberWithInt:NSLeftTextAlignment];
170    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
171    value = [NSNumber numberWithInt:NSRightTextAlignment];
172    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
173    value = [NSNumber numberWithInt:NSCenterTextAlignment];
174    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
175    value = [NSNumber numberWithInt:NSJustifiedTextAlignment];
176    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
177    value = [NSNumber numberWithInt:NSNaturalTextAlignment];
178    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
179    NSNumber *valueToSet = [NSNumber numberWithInt:500];
180    [array addObject:[GTMBindingUnitTestData testWithValue:valueToSet
181                                                 expecting:value]];
182    valueToSet = [NSNumber numberWithInt:-1];
183    [array addObject:[GTMBindingUnitTestData testWithValue:valueToSet
184                                                 expecting:value]];
185  } else if ([binding isEqualToString:NSAlternateImageBinding] || 
186             [binding isEqualToString:NSImageBinding] || 
187             [binding isEqualToString:NSMixedStateImageBinding] || 
188             [binding isEqualToString:NSOffStateImageBinding] ||
189             [binding isEqualToString:NSOnStateImageBinding]) {
190    // This handles all image bindings
191    value = [NSImage imageNamed:@"NSApplicationIcon"];
192    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
193  } else if ([binding isEqualToString:NSAnimateBinding] || 
194             [binding isEqualToString:NSDocumentEditedBinding] ||
195             [binding isEqualToString:NSEditableBinding] ||
196             [binding isEqualToString:NSEnabledBinding] ||
197             [binding isEqualToString:NSHiddenBinding] ||
198             [binding isEqualToString:NSVisibleBinding] || 
199             [binding isEqualToString:NSIsIndeterminateBinding] ||
200             // NSTranparentBinding 10.5 only
201             [binding isEqualToString:@"transparent"]) {
202    // This handles all bool value bindings
203    value = [NSNumber numberWithBool:YES];
204    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
205    value = [NSNumber numberWithBool:NO];
206    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
207  } else if ([binding isEqualToString:NSAlternateTitleBinding] ||
208             [binding isEqualToString:NSHeaderTitleBinding] ||
209             [binding isEqualToString:NSLabelBinding] ||
210             [binding isEqualToString:NSTitleBinding] ||
211             [binding isEqualToString:NSToolTipBinding]) {
212    // This handles all string value bindings
213    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@"happy"]];
214    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@""]];
215    
216    // Test some non-ascii roman text
217    char a_not_alpha[] = { 'A', 0xE2, 0x89, 0xA2, 0xCE, 0x91, '.', 0x00 };
218    value = [NSString stringWithUTF8String:a_not_alpha];
219    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
220    // Test some korean
221    char hangugo[] = { 0xED, 0x95, 0x9C, 0xEA, 0xB5, 
222                       0xAD, 0xEC, 0x96, 0xB4, 0x00 };   
223    value = [NSString stringWithUTF8String:hangugo];
224    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
225    // Test some japanese
226    char nihongo[] = { 0xE6, 0x97, 0xA5, 0xE6, 0x9C,
227                       0xAC, 0xE8, 0xAA, 0x9E, 0x00 };
228    value = [NSString stringWithUTF8String:nihongo];
229    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
230    // Test some arabic 
231    char arabic[] = { 0xd9, 0x83, 0xd8, 0xa7, 0xd9, 0x83, 0xd8, 0xa7, 0x00 };
232    value = [NSString stringWithUTF8String:arabic];
233    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
234  } else if ([binding isEqualToString:NSRepresentedFilenameBinding]) {
235    // This handles all path bindings
236    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@"/happy"]];
237    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:@"/"]];
238    
239    // Test some non-ascii roman text
240    char a_not_alpha[] = { '/', 'A', 0xE2, 0x89, 0xA2, 0xCE, 0x91, '.', 0x00 };
241    value = [NSString stringWithUTF8String:a_not_alpha];
242    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
243    // Test some korean
244    char hangugo[] = { '/', 0xED, 0x95, 0x9C, 0xEA, 0xB5, 
245      0xAD, 0xEC, 0x96, 0xB4, 0x00 };    
246    value = [NSString stringWithUTF8String:hangugo];
247    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
248    // Test some japanese
249    char nihongo[] = { '/', 0xE6, 0x97, 0xA5, 0xE6, 0x9C,
250      0xAC, 0xE8, 0xAA, 0x9E, 0x00 };
251    value = [NSString stringWithUTF8String:nihongo];
252    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
253    // Test some arabic 
254    char arabic[] = { '/', 0xd9, 0x83, 0xd8, 0xa7, 0xd9, 0x83, 0xd8, 0xa7, 0x00 };
255    value = [NSString stringWithUTF8String:arabic];
256    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
257  } else if ([binding isEqualToString:NSMaximumRecentsBinding]) {
258    value = [NSNumber numberWithInt:0];
259    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
260    value = [NSNumber numberWithInt:-1];
261    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
262    value = [NSNumber numberWithInt:INT16_MAX];
263    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
264    value = [NSNumber numberWithInt:INT16_MIN];
265    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];    
266  } else if ([binding isEqualToString:NSRowHeightBinding]) {
267     NSNumber *valueOne = [NSNumber numberWithInt:1];
268    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:valueOne]];
269    value = [NSNumber numberWithInt:0];
270    id value2 = [NSNumber numberWithInt:INT16_MIN];
271    // Row height no longer accepts <= 0 values on SnowLeopard
272    // which is a good thing.
273    if ([GTMSystemVersion isSnowLeopardOrGreater]) {
274      [array addObject:[GTMBindingUnitTestData testWithValue:value
275                                                   expecting:valueOne]];
276      
277      [array addObject:[GTMBindingUnitTestData testWithValue:value2
278                                                   expecting:valueOne]];
279    } else {
280      [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
281      [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value2]];
282    }
283    value = [NSNumber numberWithInt:INT16_MAX];
284    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
285  } else if ([binding isEqualToString:NSMaxValueBinding] ||
286             [binding isEqualToString:NSMaxWidthBinding] ||
287             [binding isEqualToString:NSMinValueBinding] ||
288             [binding isEqualToString:NSMinWidthBinding] || 
289             [binding isEqualToString:NSContentWidthBinding] || 
290             [binding isEqualToString:NSContentHeightBinding] ||
291             [binding isEqualToString:NSWidthBinding] ||
292             [binding isEqualToString:NSAnimationDelayBinding]) {
293    // NSAnimationDelay is deprecated on SnowLeopard. We continue to test it
294    // to make sure it doesn't get broken.
295      
296    // This handles all float value bindings
297    value = [NSNumber numberWithFloat:0];
298    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
299    value = [NSNumber numberWithFloat:FLT_MAX];
300    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
301    value = [NSNumber numberWithFloat:-FLT_MAX];
302    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
303    value = [NSNumber numberWithFloat:FLT_MIN];
304    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
305    value = [NSNumber numberWithFloat:-FLT_MIN];
306    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
307    value = [NSNumber numberWithFloat:FLT_EPSILON];
308    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
309    value = [NSNumber numberWithFloat:-FLT_EPSILON];
310    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
311  } else if ([binding isEqualToString:NSTextColorBinding]) {
312    // This handles all color value bindings
313    value = [NSColor colorWithCalibratedWhite:1.0 alpha:1.0];
314    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
315    value = [NSColor colorWithCalibratedWhite:1.0 alpha:0.0];
316    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
317    value = [NSColor colorWithCalibratedWhite:1.0 alpha:0.5];
318    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
319    value = [NSColor colorWithCalibratedRed:0.5 green:0.5 blue:0.5 alpha:0.5];
320    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
321    value = [NSColor colorWithDeviceCyan:0.25 magenta:0.25 yellow:0.25 
322                                   black:0.25 alpha:0.25];
323    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
324  } else if ([binding isEqualToString:NSFontBinding]) {
325    // This handles all font value bindings
326    value = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]];
327    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
328    value = [NSFont toolTipsFontOfSize:[NSFont smallSystemFontSize]];
329    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
330    value = [NSFont labelFontOfSize:144.0];
331    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
332  } else if ([binding isEqualToString:NSRecentSearchesBinding] || 
333             [binding isEqualToString:NSSortDescriptorsBinding]) {
334    // This handles all array value bindings
335    value = [NSArray array];
336    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
337  } else if ([binding isEqualToString:NSTargetBinding]) {
338    value = [NSNull null];
339    [array addObject:[GTMBindingUnitTestData testWithIdentityValue:value]];
340  } else {
341    _GTMDevLog(@"Skipped Binding: %@ for %@", binding, self);  // COV_NF_LINE
342  }
343  return array;
344}
345
346- (BOOL)gtm_unitTestIsEqualTo:(id)value {
347  return [self isEqualTo:value];
348}
349
350@end
351
352#pragma mark -
353#pragma mark All the special AppKit Bindings issues below
354
355@interface NSImage (GTMBindingUnitTestingAdditions) 
356@end
357
358@implementation NSImage (GTMBindingUnitTestingAdditions)
359- (BOOL)gtm_unitTestIsEqualTo:(id)value {
360  // NSImage just does pointer equality in the default isEqualTo implementation
361  // we need something a little more heavy duty that actually compares the
362  // images internally.
363  return [[self TIFFRepresentation] isEqualTo:[value TIFFRepresentation]];
364}
365@end
366
367@interface NSScroller (GTMBindingUnitTestingAdditions) 
368@end
369
370@implementation NSScroller (GTMBindingUnitTestingAdditions)
371- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
372  NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
373  SInt32 major, minor, bugFix;
374  [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
375  if (major <= 10 && minor <= 5 && bugFix <= 5) {
376    // rdar://5849154 - NSScroller exposes binding with no value 
377    //                  class for NSValueBinding
378    [array addObject:NSValueBinding];
379  }
380  if (major <= 10 && minor <= 6) {
381    // Broken on SnowLeopard and below
382    // rdar://5849236 - NSScroller exposes binding for NSFontBinding
383    [array addObject:NSFontBinding];
384  }
385  return array;
386}
387@end
388
389@interface NSTextField (GTMBindingUnitTestingAdditions) 
390@end
391
392@implementation NSTextField (GTMBindingUnitTestingAdditions)
393
394- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
395  NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
396  // Not KVC Compliant
397  for (int i = 0; i < 10; i++) {
398    [array addObject:[NSString stringWithFormat:@"displayPatternValue%d", i]];
399  }
400  return array;
401}
402
403- (NSMutableArray *)gtm_unitTestExposedBindingsTestValues:(NSString*)binding {
404  NSMutableArray *array = [super gtm_unitTestExposedBindingsTestValues:binding];
405  if ([binding isEqualToString:NSAlignmentBinding]) {
406    SInt32 major, minor, bugFix;
407    [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
408    if (major <= 10 && minor <= 6) {
409      // rdar://5851487 - If NSAlignmentBinding for a NSTextField is set to -1 
410      //                  and then got it returns 7
411      NSNumber *textAlignment = [NSNumber numberWithInt:NSNaturalTextAlignment];
412      GTMBindingUnitTestData *dataToRemove =
413        [GTMBindingUnitTestData testWithValue:[NSNumber numberWithInt:-1] 
414                                    expecting:textAlignment];
415      [array removeObject:dataToRemove];
416      GTMBindingUnitTestData *dataToAdd =
417        [GTMBindingUnitTestData testWithValue:[NSNumber numberWithInt:-1] 
418                                    expecting:[NSNumber numberWithInt:7]];
419      [array addObject:dataToAdd];
420    }
421  }
422  return array;
423}
424@end
425
426@interface NSSearchField (GTMBindingUnitTestingAdditions) 
427@end
428
429@implementation NSSearchField (GTMBindingUnitTestingAdditions)
430
431- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
432  NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
433  SInt32 major, minor, bugFix;
434  [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
435  if (major <= 10 && minor <= 6) {
436    // rdar://5851491 - Setting NSAlignmentBinding of search field to 
437    //                  NSCenterTextAlignment broken
438    // Broken on 10.6 and below.
439    [array addObject:NSAlignmentBinding];
440  }
441  // Not KVC Compliant
442  [array addObject:NSPredicateBinding];
443  return array;
444}
445
446@end
447
448@interface NSWindow (GTMBindingUnitTestingAdditions) 
449@end
450
451@implementation NSWindow (GTMBindingUnitTestingAdditions)
452
453- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
454  NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
455  // Not KVC Compliant
456  [array addObject:NSContentWidthBinding];
457  [array addObject:NSContentHeightBinding];
458  for (int i = 0; i < 10; i++) {
459    [array addObject:[NSString stringWithFormat:@"displayPatternTitle%d", i]];
460  }
461  return array;
462}
463
464@end
465
466@interface NSBox (GTMBindingUnitTestingAdditions) 
467@end
468
469@implementation NSBox (GTMBindingUnitTestingAdditions)
470
471- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
472  NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
473  // Not KVC Compliant
474  for (int i = 0; i < 10; i++) {
475    [array addObject:[NSString stringWithFormat:@"displayPatternTitle%d", i]];
476  }
477  return array;
478}
479
480@end
481
482@interface NSTableView (GTMBindingUnitTestingAdditions) 
483@end
484
485@implementation NSTableView (GTMBindingUnitTestingAdditions)
486
487- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
488  NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
489  SInt32 major, minor, bugFix;
490  [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
491  if (major <= 10 && minor <= 6) {
492    // rdar://6288332 - NSTableView does not respond to NSFontBinding
493    // Broken on 10.5 and SnowLeopard
494    [array addObject:NSFontBinding];
495  }
496  // Not KVC Compliant
497  [array addObject:NSContentBinding];
498  [array addObject:NSDoubleClickTargetBinding];
499  [array addObject:NSDoubleClickArgumentBinding];
500  [array addObject:NSSelectionIndexesBinding];
501  return array;
502}
503
504@end
505
506@interface NSTextView (GTMBindingUnitTestingAdditions) 
507@end
508
509@implementation NSTextView (GTMBindingUnitTestingAdditions)
510
511- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
512  NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
513  SInt32 major, minor, bugFix;
514  [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
515  if (major <= 10 && minor <= 6) {
516    //rdar://5849335 - NSTextView only partially KVC compliant for key 
517    //                 NSAttributedStringBinding
518    [array addObject:NSAttributedStringBinding];
519  }
520  // Not KVC Compliant
521  [array addObject:NSDataBinding];
522  [array addObject:NSValueURLBinding];
523  [array addObject:NSValuePathBinding];
524  return array;
525}
526
527@end
528
529@interface NSTabView (GTMBindingUnitTestingAdditions) 
530@end
531
532@implementation NSTabView (GTMBindingUnitTestingAdditions)
533
534- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
535  NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
536  SInt32 major, minor, bugFix;
537  [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
538  if (major <= 10 && minor <= 6) {
539    // rdar://5849248 - NSTabView exposes binding with no value class 
540    //                  for NSSelectedIdentifierBinding 
541    [array addObject:NSSelectedIdentifierBinding];
542  }
543  // Not KVC Compliant
544  [array addObject:NSSelectedIndexBinding];
545  [array addObject:NSSelectedLabelBinding];
546  return array;
547}
548
549@end
550
551@interface NSButton (GTMBindingUnitTestingAdditions) 
552@end
553
554@implementation NSButton (GTMBindingUnitTestingAdditions)
555
556- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
557  NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
558  // Not KVC Compliant
559  [array addObject:NSArgumentBinding];
560  return array;
561}
562
563@end
564
565@interface NSProgressIndicator (GTMBindingUnitTestingAdditions) 
566@end
567
568@implementation NSProgressIndicator (GTMBindingUnitTestingAdditions)
569
570- (NSMutableArray*)gtm_unitTestExposedBindingsToIgnore {
571  NSMutableArray *array = [super gtm_unitTestExposedBindingsToIgnore];
572  // Not KVC Compliant
573  [array addObject:NSAnimateBinding];
574  return array;
575}
576
577@end