Skip to content

Commit

Permalink
Add basic KVO test.
Browse files Browse the repository at this point in the history
Add a simple KVO test just to verify that KVO continues to function for protobufs.
  • Loading branch information
dmaclach authored and thomasvl committed Jun 12, 2021
1 parent d1ef6d9 commit 36e9bfc
Showing 1 changed file with 95 additions and 0 deletions.
95 changes: 95 additions & 0 deletions objectivec/Tests/GPBMessageTests.m
Expand Up @@ -41,6 +41,52 @@
#import "google/protobuf/Unittest.pbobjc.h"
#import "google/protobuf/UnittestObjc.pbobjc.h"
#import "google/protobuf/UnittestObjcOptions.pbobjc.h"
#import "google/protobuf/UnittestImport.pbobjc.h"

// Helper class to test KVO.
@interface GPBKVOTestObserver : NSObject {
id observee_;
NSString *keyPath_;
}

@property (nonatomic) BOOL didObserve;
- (id)initWithObservee:(id)observee keyPath:(NSString *)keyPath;
@end

@implementation GPBKVOTestObserver

@synthesize didObserve;

- (id)initWithObservee:(id)observee keyPath:(NSString *)keyPath {
if (self = [super init]) {
observee_ = [observee retain];
keyPath_ = [keyPath copy];
[observee_ addObserver:self forKeyPath:keyPath_ options:0 context:NULL];
}
return self;
}

- (void)dealloc {
[observee_ removeObserver:self forKeyPath:keyPath_];
[observee_ release];
[keyPath_ release];
[super dealloc];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
#pragma unused(object)
#pragma unused(change)
#pragma unused(context)
if ([keyPath isEqualToString:keyPath_]) {
self.didObserve = YES;
}
}

@end

@interface MessageTests : GPBTestCase
@end
Expand Down Expand Up @@ -431,6 +477,55 @@ - (void)testKVC_SetValue_ForKey {
[self assertAllFieldsKVCMatch:message];
}

- (void)testKVOBasic {
TestAllTypes *message = [TestAllTypes message];
GPBKVOTestObserver *observer =
[[[GPBKVOTestObserver alloc] initWithObservee:message
keyPath:@"optionalString"]
autorelease];
XCTAssertFalse(observer.didObserve);
message.defaultString = @"Hello";
XCTAssertFalse(observer.didObserve);
message.optionalString = @"Hello";
XCTAssertTrue(observer.didObserve);
}

- (void)testKVOAutocreate {
TestAllTypes *message = [TestAllTypes message];
GPBKVOTestObserver *autocreateObserver =
[[[GPBKVOTestObserver alloc] initWithObservee:message
keyPath:@"optionalImportMessage"]
autorelease];
GPBKVOTestObserver *innerFieldObserver =
[[[GPBKVOTestObserver alloc] initWithObservee:message
keyPath:@"optionalImportMessage.d"]
autorelease];
XCTAssertFalse(autocreateObserver.didObserve);
XCTAssertFalse(innerFieldObserver.didObserve);

int a = message.optionalImportMessage.d;
XCTAssertEqual(a, 0);

// Autocreation of fields is not observed by KVO when getting values.
XCTAssertFalse(autocreateObserver.didObserve);
XCTAssertFalse(innerFieldObserver.didObserve);

message.optionalImportMessage.d = 2;

// Autocreation of fields is not observed by KVO.
// This is undefined behavior. The library makes no guarantees with regards
// to KVO firing if an autocreation occurs as part of a setter.
// This test exists just to be aware if the behavior changes.
XCTAssertFalse(autocreateObserver.didObserve);

// Values set inside of an autocreated field are observed.
XCTAssertTrue(innerFieldObserver.didObserve);

// Explicit setting of a message field is observed.
message.optionalImportMessage = [ImportMessage message];
XCTAssertTrue(autocreateObserver.didObserve);
}

- (void)testDescription {
// No real test, just exercise code
TestAllTypes *message = [TestAllTypes message];
Expand Down

0 comments on commit 36e9bfc

Please sign in to comment.