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