Skip to content

Unify and provide consistent client-side error and exception reporting. #897

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 16 additions & 17 deletions Parse/Internal/FieldOperation/PFFieldOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@
@implementation PFFieldOperation

- (id)encodeWithObjectEncoder:(PFEncoder *)objectEncoder {
PFConsistencyAssert(NO, @"Operation is invalid.");
PFConsistencyAssertionFailure(@"Operation is invalid.");
return nil;
}

- (PFFieldOperation *)mergeWithPrevious:(PFFieldOperation *)previous {
PFConsistencyAssert(NO, @"Operation is invalid.");
PFConsistencyAssertionFailure(@"Operation is invalid.");
return nil;
}

- (id)applyToValue:(id)oldValue forKey:(NSString *)key {
PFConsistencyAssert(NO, @"Operation is invalid.");
PFConsistencyAssertionFailure(@"Operation is invalid.");
return nil;
}

Expand Down Expand Up @@ -153,7 +153,7 @@ - (PFFieldOperation *)mergeWithPrevious:(PFFieldOperation *)previous {
withNumber:((PFIncrementOperation *)previous).amount];
return [PFIncrementOperation incrementWithAmount:newAmount];
}
[NSException raise:NSInternalInconsistencyException format:@"Operation is invalid after previous operation."];
PFConsistencyAssertionFailure(@"This operation is invalid after previous operation.");
return nil;
}

Expand Down Expand Up @@ -208,15 +208,15 @@ - (PFFieldOperation *)mergeWithPrevious:(PFFieldOperation *)previous {
NSArray *newArray = [oldArray arrayByAddingObjectsFromArray:self.objects];
return [PFSetOperation setWithValue:newArray];
} else {
[NSException raise:NSInternalInconsistencyException format:@"You can't add an item to a non-array."];
PFConsistencyAssertionFailure(@"Unable to add an item to a non-array.");
return nil;
}
} else if ([previous isKindOfClass:[PFAddOperation class]]) {
NSMutableArray *newObjects = [((PFAddOperation *)previous).objects mutableCopy];
[newObjects addObjectsFromArray:self.objects];
return [[self class] addWithObjects:newObjects];
}
[NSException raise:NSInternalInconsistencyException format:@"Operation is invalid after previous operation."];
PFConsistencyAssertionFailure(@"This operation is invalid after previous operation.");
return nil;
}

Expand All @@ -226,7 +226,7 @@ - (id)applyToValue:(id)oldValue forKey:(NSString *)key {
} else if ([oldValue isKindOfClass:[NSArray class]]) {
return [((NSArray *)oldValue)arrayByAddingObjectsFromArray:self.objects];
}
[NSException raise:NSInternalInconsistencyException format:@"Operation is invalid after previous operation."];
PFConsistencyAssertionFailure(@"This operation is invalid after previous operation.");
return nil;
}

Expand Down Expand Up @@ -267,14 +267,14 @@ - (PFFieldOperation *)mergeWithPrevious:(PFFieldOperation *)previous {
NSArray *oldArray = (((PFSetOperation *)previous).value);
return [PFSetOperation setWithValue:[self applyToValue:oldArray forKey:nil]];
} else {
[NSException raise:NSInternalInconsistencyException format:@"You can't add an item to a non-array."];
PFConsistencyAssertionFailure(@"Unable to add an item to a non-array.");
return nil;
}
} else if ([previous isKindOfClass:[PFAddUniqueOperation class]]) {
NSArray *previousObjects = ((PFAddUniqueOperation *)previous).objects;
return [[self class] addUniqueWithObjects:[self applyToValue:previousObjects forKey:nil]];
}
[NSException raise:NSInternalInconsistencyException format:@"Operation is invalid after previous operation."];
PFConsistencyAssertionFailure(@"This operation is invalid after previous operation.");
return nil;
}

Expand Down Expand Up @@ -302,7 +302,7 @@ - (id)applyToValue:(id)oldValue forKey:(NSString *)key {
}
return newValue;
}
[NSException raise:NSInternalInconsistencyException format:@"Operation is invalid after previous operation."];
PFConsistencyAssertionFailure(@"This operation is invalid after previous operation.");
return nil;
}

Expand Down Expand Up @@ -336,22 +336,22 @@ - (PFFieldOperation *)mergeWithPrevious:(PFFieldOperation *)previous {
if (!previous) {
return self;
} else if ([previous isKindOfClass:[PFDeleteOperation class]]) {
[NSException raise:NSInternalInconsistencyException format:@"You can't remove items from a deleted array."];
PFConsistencyAssertionFailure(@"Unable to remove items from a deleted array.");
return nil;
} else if ([previous isKindOfClass:[PFSetOperation class]]) {
if ([((PFSetOperation *)previous).value isKindOfClass:[NSArray class]]) {
NSArray *oldArray = ((PFSetOperation *)previous).value;
return [PFSetOperation setWithValue:[self applyToValue:oldArray forKey:nil]];
} else {
[NSException raise:NSInternalInconsistencyException format:@"You can't add an item to a non-array."];
PFConsistencyAssertionFailure(@"Unable to add an item to a non-array.");
return nil;
}
} else if ([previous isKindOfClass:[PFRemoveOperation class]]) {
NSArray *newObjects = [((PFRemoveOperation *)previous).objects arrayByAddingObjectsFromArray:self.objects];
return [PFRemoveOperation removeWithObjects:newObjects];
}

[NSException raise:NSInternalInconsistencyException format:@"Operation is invalid after previous operation."];
PFConsistencyAssertionFailure(@"This operation is invalid after previous operation.");
return nil;
}

Expand Down Expand Up @@ -379,7 +379,7 @@ - (id)applyToValue:(id)oldValue forKey:(NSString *)key {
}
return newValue;
}
[NSException raise:NSInternalInconsistencyException format:@"Operation is invalid after previous operation."];
PFConsistencyAssertionFailure(@"This operation is invalid after previous operation.");
return nil;
}

Expand Down Expand Up @@ -474,8 +474,7 @@ - (id)encodeWithObjectEncoder:(PFEncoder *)objectEncoder {
if (removeDict) {
return removeDict;
}

[NSException raise:NSInternalInconsistencyException format:@"A PFRelationOperation was created without any data."];
PFConsistencyAssertionFailure(@"A PFRelationOperation was created without any data.");
return nil;
}

Expand Down Expand Up @@ -535,7 +534,7 @@ - (id)applyToValue:(id)oldValue forKey:(NSString *)key {
}
}
} else {
[NSException raise:NSInternalInconsistencyException format:@"Operation is invalid after previous operation."];
PFConsistencyAssertionFailure(@"This operation is invalid after previous operation.");
return nil;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ - (BFTask *)processFetchResultAsync:(NSDictionary *)result forObject:(PFObject *
///--------------------------------------

- (BFTask *)deleteObjectAsync:(PFObject *)object withSessionToken:(nullable NSString *)sessionToken {
PFConsistencyAssert(NO, @"Installations cannot be deleted.");
PFConsistencyAssertionFailure(@"Installations cannot be deleted.");
return nil;
}

- (BFTask *)processDeleteResultAsync:(nullable NSDictionary *)result forObject:(PFObject *)object {
PFConsistencyAssert(NO, @"Installations cannot be deleted.");
PFConsistencyAssertionFailure(@"Installations cannot be deleted.");
return nil;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ - (id)valueForContainer:(id)container
return [self valueForContainer:restFormat key:rest depth:depth + 1];
}
}
[NSException raise:NSInvalidArgumentException format:@"Key %@ is invalid", key];
PFParameterAssertionFailure(@"Key %@ is invalid.", key);
}
return [self valueForContainer:value key:rest depth:depth + 1];
}
Expand All @@ -152,7 +152,7 @@ - (id)valueForContainer:(id)container
} else if (container == nil) {
return nil;
} else {
[NSException raise:NSInvalidArgumentException format:@"Bad key %@", key];
PFParameterAssertionFailure(@"Bad key %@", key);
// Shouldn't reach here.
return nil;
}
Expand Down Expand Up @@ -457,9 +457,7 @@ + (BOOL)matchesValue:(id)value
} else if ([operator isEqualToString:PFQueryKeyWithin]) {
return [self matchesValue:value within:constraint];
}

[NSException raise:NSInvalidArgumentException
format:@"The offline store does not yet support %@ operator.", operator];
PFParameterAssertionFailure(@"Local Datastore does not yet support %@ operator.", operator);
// Shouldn't reach here
return YES;
}
Expand Down Expand Up @@ -710,10 +708,9 @@ - (BFTask *)fetchIncludeAsync:(NSString *)include
// throwing an exception.
return nil;
}
NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException
reason:@"include is invalid"
userInfo:nil];
return [BFTask taskWithException:exception];
NSError *error = [PFErrorUtilities errorWithCode:kPFErrorInvalidNestedKey
message:@"include is invalid"];
return [BFTask taskWithError:error];
}] continueWithSuccessBlock:^id(BFTask *task) {
return [self fetchIncludeAsync:rest container:task.result database:database];
}];
Expand Down
25 changes: 11 additions & 14 deletions Parse/Internal/LocalDataStore/OfflineStore/PFOfflineStore.m
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,7 @@ - (instancetype)initWithFileManager:(PFFileManager *)fileManager options:(PFOffl
PFOfflineStoreKeyOfJSON, PFOfflineStoreTableOfObjects, PFOfflineStoreKeyOfUUID];
return [database executeQueryAsync:query withArgumentsInArray:@[ uuid ] block:^id(PFSQLiteDatabaseResult *_Nonnull result) {
if (![result next]) {
[NSException raise:NSInternalInconsistencyException
format:@"Attempted to find non-existent uuid %@.", uuid];
PFConsistencyAssertionFailure(@"Attempted to find non-existent uuid %@. Please report this issue with stack traces and logs.", uuid);
}
return [result stringForColumnIndex:0];
}];
Expand All @@ -189,10 +188,10 @@ - (instancetype)initWithFileManager:(PFFileManager *)fileManager options:(PFOffl
if (uuidTask && !(self.options & PFOfflineStoreOptionAlwaysFetchFromSQLite)) {
// This object is an existing ParseObject, and we must've already pulled its data
// out of the offline store, or else we wouldn't know its UUID. This should never happen.
NSString *message = @"Object must have already been fetched but isn't marked as fetched.";
[tcs setException:[NSException exceptionWithName:NSInternalInconsistencyException
reason:message
userInfo:nil]];
NSError *error = [PFErrorUtilities errorWithCode:kPFErrorObjectNotFound
message:@"Object must have already been fetched but isn't marked as fetched."
shouldLog:NO];
[tcs setError:error];

@synchronized(self.lock) {
[self.fetchedObjects removeObjectForKey:object];
Expand All @@ -215,9 +214,8 @@ - (instancetype)initWithFileManager:(PFFileManager *)fileManager options:(PFOffl
__block NSString *newUUID = nil;
jsonStringTask = [[database executeQueryAsync:query withArgumentsInArray:@[ className, objectId ] block:^id(PFSQLiteDatabaseResult *_Nonnull result) {
if (![result next]) {
NSString *errorMessage = @"This object is not available in the offline cache.";
NSError *error = [PFErrorUtilities errorWithCode:kPFErrorCacheMiss
message:errorMessage
message:@"This object is not available in the offline cache."
shouldLog:NO];
return [BFTask taskWithError:error];
}
Expand Down Expand Up @@ -581,10 +579,10 @@ - (BFTask *)findAsyncForQueryState:(PFQueryState *)queryState
@synchronized(self.lock) {
fetchTask = [self.fetchedObjects objectForKey:object];
if (!fetchTask) {
NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException
reason:@"An object cannot be updated if it wasn't fetched"
userInfo:nil];
return [BFTask taskWithException:exception];
NSError *error = [PFErrorUtilities errorWithCode:kPFErrorObjectNotFound
message:@"An object cannot be updated if it wasn't fetched"
shouldLog:NO];
return [BFTask taskWithError:error];
}
}
return [fetchTask continueWithBlock:^id(BFTask *task) {
Expand Down Expand Up @@ -909,8 +907,7 @@ - (BFTask *)findAsyncForQueryState:(PFQueryState *)queryState
__block NSString *objectId = nil;
return [[database executeQueryAsync:query withArgumentsInArray:@[ uuid ] block:^id(PFSQLiteDatabaseResult *result) {
if (![result next]) {
[NSException raise:NSInternalInconsistencyException
format:@"Attempted to find non-existent uuid %@", uuid]; // TODO: (nlutsenko) Convert to errors.
PFConsistencyAssertionFailure(@"Attempted to find non-existent uuid %@. Please report this issue with stack traces and logs.", uuid);
}

className = [result stringForColumnIndex:0];
Expand Down
47 changes: 32 additions & 15 deletions Parse/Internal/PFAssert.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,40 +24,57 @@
} \
} while(0)

/**
Raises an `NSInvalidArgumentException`. Use `description` to supply the way to fix the exception.
*/
#define PFParameterAssertionFailure(description, ...) \
do {\
[NSException raise:NSInvalidArgumentException \
format:description, ##__VA_ARGS__]; \
} while(0)

/**
Raises an `NSRangeException` if the `condition` does not pass.
Use `description` to supply the way to fix the exception.
*/
#define PFRangeAssert(condition, description, ...) \
do {\
if (!(condition)) { \
[NSException raise:NSRangeException \
format:description, ##__VA_ARGS__]; \
} \
do {\
if (!(condition)) { \
[NSException raise:NSRangeException \
format:description, ##__VA_ARGS__]; \
} \
} while(0)

/**
Raises an `NSInternalInconsistencyException` if the `condition` does not pass.
Use `description` to supply the way to fix the exception.
*/
#define PFConsistencyAssert(condition, description, ...) \
do { \
if (!(condition)) { \
[NSException raise:NSInternalInconsistencyException \
format:description, ##__VA_ARGS__]; \
} \
} while(0)
do { \
if (!(condition)) { \
[NSException raise:NSInternalInconsistencyException \
format:description, ##__VA_ARGS__]; \
} \
} while(0)

/**
Raises an `NSInternalInconsistencyException`. Use `description` to supply the way to fix the exception.
*/
#define PFConsistencyAssertionFailure(description, ...) \
do {\
[NSException raise:NSInternalInconsistencyException \
format:description, ##__VA_ARGS__]; \
} while(0)

/**
Always raises `NSInternalInconsistencyException` with details
about the method used and class that received the message
*/
#define PFNotDesignatedInitializer() \
do { \
PFConsistencyAssert(NO, \
@"%@ is not the designated initializer for instances of %@.", \
NSStringFromSelector(_cmd), \
NSStringFromClass([self class])); \
PFConsistencyAssertionFailure(@"%@ is not the designated initializer for instances of %@.", \
NSStringFromSelector(_cmd), \
NSStringFromClass([self class])); \
return nil; \
} while (0)

Expand Down
5 changes: 1 addition & 4 deletions Parse/Internal/PFEncoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ - (id)encodeObject:(id)object {
// Returning this empty object is strictly wrong, but we have to have *something*
// to put into an object's mutable container cache, and this is just about the
// best we can do right now.
//
// [NSException raise:NSInternalInconsistencyException
// format:@"Tried to serialize an unsaved file."];
return @{ @"__type" : @"File" };
}
return @{
Expand Down Expand Up @@ -122,7 +119,7 @@ + (instancetype)objectEncoder {
}

- (id)encodeParseObject:(PFObject *)object {
[NSException raise:NSInternalInconsistencyException format:@"PFObjects are not allowed here."];
PFConsistencyAssertionFailure(@"PFObjects are not allowed here.");
return nil;
}

Expand Down
9 changes: 4 additions & 5 deletions Parse/Internal/PFEventuallyQueue.m
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,10 @@ - (BFTask *)_runCommand:(id<PFNetworkCommand>)command withIdentifier:(NSString *
return [self.dataSource.commandRunner runCommandAsync:(PFRESTCommand *)command withOptions:0];
}

NSString *reason = [NSString stringWithFormat:@"Can't find a compatible runner for command %@.", command];
NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException
reason:reason
userInfo:nil];
return [BFTask taskWithException:exception];
NSError *error = [PFErrorUtilities errorWithCode:kPFErrorInternalServer
message:[NSString stringWithFormat:@"Can't find a compatible runner for command %@.", command]
shouldLog:NO];
return [BFTask taskWithError:error];
}

- (BFTask *)_didFinishRunningCommand:(id<PFNetworkCommand>)command
Expand Down
3 changes: 1 addition & 2 deletions Parse/Internal/PFInternalUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,7 @@ + (void)appendObject:(id)object toString:(NSMutableString *)string {
} else if ([object isKindOfClass:[NSNull class]]) {
[self appendNullToString:string];
} else {
[NSException raise:NSInvalidArgumentException
format:@"Couldn't create cache key from %@", object];
PFParameterAssertionFailure(@"Couldn't create cache key from %@", object);
}
}

Expand Down
8 changes: 4 additions & 4 deletions Parse/Internal/PFPinningEventuallyQueue.m
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,10 @@ - (BFTask *)_waitForOperationSet:(PFOperationSet *)operationSet eventuallyPin:(P
}
});
if (uuid == nil) {
NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException
reason:@"Either operationSet or eventuallyPin must be set"
userInfo:nil];
return [BFTask taskWithException:exception];
NSError *error = [PFErrorUtilities errorWithCode:kPFErrorIncorrectType
message:@"Either operationSet or eventuallyPin must be set"
shouldLog:NO];
return [BFTask taskWithError:error];
}
return [BFTask taskWithResult:nil];
}
Expand Down
Loading