Skip to content

Commit

Permalink
Use typed crash reports (#516)
Browse files Browse the repository at this point in the history
* Use typed crash reports

* Add missing imports

* Log errors

* Fix JSON codec to check key type

* Add isEqual to report

* Fix JSON filter

* Fix combine filter

* Update tests

* Add description method

* Fix missing import

* Add missing logger imports

* Add report type enum

* Rename value type
  • Loading branch information
bamx23 committed Jun 25, 2024
1 parent 3a3b99e commit 989497e
Show file tree
Hide file tree
Showing 21 changed files with 593 additions and 521 deletions.
15 changes: 8 additions & 7 deletions Sources/KSCrashFilters/KSCrashReportFilterAlert.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#import "KSCrashReportFilterAlert.h"

#import "KSSystemCapabilities.h"
#import "KSCrashReport.h"

//#define KSLogger_LocalLevel TRACE
#import "KSLogger.h"
Expand All @@ -39,11 +40,11 @@

#if KSCRASH_HAS_NSALERT
#import <AppKit/AppKit.h>
#endif
#endif

@interface KSCrashAlertViewProcess : NSObject

@property(nonatomic,readwrite,retain) NSArray* reports;
@property(nonatomic,readwrite,copy) NSArray<KSCrashReport*>* reports;
@property(nonatomic,readwrite,copy) KSCrashReportFilterCompletion onCompletion;
@property(nonatomic,readwrite,assign) NSInteger expectedButtonIndex;

Expand All @@ -53,7 +54,7 @@ - (void) startWithTitle:(NSString*) title
message:(NSString*) message
yesAnswer:(NSString*) yesAnswer
noAnswer:(NSString*) noAnswer
reports:(NSArray*) reports
reports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion;

@end
Expand All @@ -73,11 +74,11 @@ - (void) startWithTitle:(NSString*) title
message:(NSString*) message
yesAnswer:(NSString*) yesAnswer
noAnswer:(NSString*) noAnswer
reports:(NSArray*) reports
reports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion
{
KSLOG_TRACE(@"Starting alert view process");
self.reports = reports;
self.reports = [reports copy];
self.onCompletion = onCompletion;
self.expectedButtonIndex = noAnswer == nil ? 0 : 1;

Expand Down Expand Up @@ -170,7 +171,7 @@ - (instancetype) initWithTitle:(NSString*) title
return self;
}

- (void) filterReports:(NSArray*) reports
- (void) filterReports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion
{
dispatch_async(dispatch_get_main_queue(), ^
Expand Down Expand Up @@ -225,7 +226,7 @@ - (id) initWithTitle:(__unused NSString*) title
return self;
}

- (void) filterReports:(NSArray*) reports
- (void) filterReports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion
{
KSLOG_WARN(@"Alert filter not available on this platform.");
Expand Down
24 changes: 17 additions & 7 deletions Sources/KSCrashFilters/KSCrashReportFilterAppleFmt.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#import "KSCrashReportFilterAppleFmt.h"
#import "KSSystemCapabilities.h"
#import "KSCrashReport.h"

#import <inttypes.h>
#import <mach/machine.h>
Expand All @@ -36,6 +37,9 @@
#import "KSJSONCodecObjC.h"
#import "KSCPU.h"

//#define KSLogger_LocalLevel TRACE
#import "KSLogger.h"

#if defined(__LP64__)
#define FMT_LONG_DIGITS "16"
#define FMT_RJ_SPACES "18"
Expand Down Expand Up @@ -219,18 +223,24 @@ - (int) majorVersion:(NSDictionary*) report
return 0;
}

- (void) filterReports:(NSArray*) reports
- (void) filterReports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion
{
NSMutableArray* filteredReports = [NSMutableArray arrayWithCapacity:[reports count]];
for(NSDictionary* report in reports)
NSMutableArray<KSCrashReport*>* filteredReports = [NSMutableArray arrayWithCapacity:[reports count]];
for(KSCrashReport* report in reports)
{
if([self majorVersion:report] == kExpectedMajorVersion)
NSDictionary *reportDict = report.dictionaryValue;
if(reportDict == nil)
{
KSLOG_ERROR(@"Unexpected non-dictionary report: %@", report);
continue;
}
if([self majorVersion:reportDict] == kExpectedMajorVersion)
{
id appleReport = [self toAppleFormat:report];
if(appleReport != nil)
NSString* appleReportString = [self toAppleFormat:reportDict];
if(appleReportString != nil)
{
[filteredReports addObject:appleReport];
[filteredReports addObject:[KSCrashReport reportWithString:appleReportString]];
}
}
}
Expand Down
149 changes: 54 additions & 95 deletions Sources/KSCrashFilters/KSCrashReportFilterBasic.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#import "NSError+SimpleConstructor.h"
#import "Container+DeepSearch.h"
#import "KSVarArgs.h"
#import "KSCrashReport.h"

//#define KSLogger_LocalLevel TRACE
#import "KSLogger.h"
Expand All @@ -41,7 +42,7 @@ + (instancetype) filter
return [[self alloc] init];
}

- (void) filterReports:(NSArray*) reports
- (void) filterReports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion
{
kscrash_callCompletion(onCompletion, reports, YES, nil);
Expand Down Expand Up @@ -132,7 +133,7 @@ - (instancetype) initWithFiltersAndKeys:(id) firstFilter, ...
return [self initWithFilters:filters keys:keys];
}

- (void) filterReports:(NSArray*) reports
- (void) filterReports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion
{
NSArray* filters = self.filters;
Expand Down Expand Up @@ -168,7 +169,7 @@ - (void) filterReports:(NSArray*) reports
filterCompletion = nil;
});
} copy];
filterCompletion = [^(NSArray* filteredReports,
filterCompletion = [^(NSArray<KSCrashReport*>* filteredReports,
BOOL completed,
NSError* filterError)
{
Expand Down Expand Up @@ -204,20 +205,21 @@ - (void) filterReports:(NSArray*) reports
// All filters complete, or a filter failed.
// Build final "filteredReports" array.
NSUInteger reportCount = [(NSArray*)[reportSets objectAtIndex:0] count];
NSMutableArray* combinedReports = [NSMutableArray arrayWithCapacity:reportCount];
NSMutableArray<KSCrashReport*>* combinedReports = [NSMutableArray arrayWithCapacity:reportCount];
for(NSUInteger iReport = 0; iReport < reportCount; iReport++)
{
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:filterCount];
for(NSUInteger iSet = 0; iSet < filterCount; iSet++)
{
NSArray* reportSet = [reportSets objectAtIndex:iSet];
if(reportSet.count>iReport){
NSDictionary* report = [reportSet objectAtIndex:iReport];
[dict setObject:report
forKey:[keys objectAtIndex:iSet]];
NSString* key = keys[iSet];
NSArray* reportSet = reportSets[iSet];
if(iReport < reportSet.count){
KSCrashReport* report = reportSet[iReport];
dict[key] = report.dictionaryValue ?: report.stringValue ?: report.dataValue;
}
}
[combinedReports addObject:dict];
KSCrashReport* report = [KSCrashReport reportWithDictionary:dict];
[combinedReports addObject:report];
}

kscrash_callCompletion(onCompletion, combinedReports, completed, filterError);
Expand Down Expand Up @@ -288,7 +290,7 @@ - (void) addFilter:(id<KSCrashReportFilter>) filter
self.filters = [@[filter] arrayByAddingObjectsFromArray:self.filters];
}

- (void) filterReports:(NSArray*) reports
- (void) filterReports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion
{
NSArray* filters = self.filters;
Expand All @@ -311,7 +313,7 @@ - (void) filterReports:(NSArray*) reports
filterCompletion = nil;
});
} copy];
filterCompletion = [^(NSArray* filteredReports,
filterCompletion = [^(NSArray<KSCrashReport*>* filteredReports,
BOOL completed,
NSError* filterError)
{
Expand Down Expand Up @@ -358,71 +360,6 @@ - (void) filterReports:(NSArray*) reports
@end


@interface KSCrashReportFilterObjectForKey ()

@property(nonatomic, readwrite, retain) id key;
@property(nonatomic, readwrite, assign) BOOL allowNotFound;

@end

@implementation KSCrashReportFilterObjectForKey

@synthesize key = _key;
@synthesize allowNotFound = _allowNotFound;

+ (instancetype) filterWithKey:(id)key allowNotFound:(BOOL) allowNotFound
{
return [[self alloc] initWithKey:key allowNotFound:allowNotFound];
}

- (instancetype) initWithKey:(id)key allowNotFound:(BOOL) allowNotFound
{
if((self = [super init]))
{
self.key = key;
self.allowNotFound = allowNotFound;
}
return self;
}

- (void) filterReports:(NSArray*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion
{
NSMutableArray* filteredReports = [NSMutableArray arrayWithCapacity:[reports count]];
for(NSDictionary* report in reports)
{
id object = nil;
if([self.key isKindOfClass:[NSString class]])
{
object = [report objectForKeyPath:self.key];
}
else
{
object = [report objectForKey:self.key];
}
if(object == nil)
{
if(!self.allowNotFound)
{
kscrash_callCompletion(onCompletion, filteredReports, NO,
[NSError errorWithDomain:[[self class] description]
code:0
description:@"Key not found: %@", self.key]);
return;
}
[filteredReports addObject:[NSDictionary dictionary]];
}
else
{
[filteredReports addObject:object];
}
}
kscrash_callCompletion(onCompletion, filteredReports, YES, nil);
}

@end


@interface KSCrashReportFilterConcatenate ()

@property(nonatomic, readwrite, retain) NSString* separatorFmt;
Expand Down Expand Up @@ -475,11 +412,11 @@ - (instancetype) initWithSeparatorFmt:(NSString*) separatorFmt keysArray:(NSArra
return self;
}

- (void) filterReports:(NSArray*) reports
- (void) filterReports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion
{
NSMutableArray* filteredReports = [NSMutableArray arrayWithCapacity:[reports count]];
for(NSDictionary* report in reports)
for(KSCrashReport* report in reports)
{
BOOL firstEntry = YES;
NSMutableString* concatenated = [NSMutableString string];
Expand All @@ -493,7 +430,7 @@ - (void) filterReports:(NSArray*) reports
{
[concatenated appendFormat:self.separatorFmt, key];
}
id object = [report objectForKeyPath:key];
id object = [report.dictionaryValue objectForKeyPath:key];
[concatenated appendFormat:@"%@", object];
}
[filteredReports addObject:concatenated];
Expand Down Expand Up @@ -553,16 +490,23 @@ - (instancetype) initWithKeysArray:(NSArray<NSString*>*) keyPaths
return self;
}

- (void) filterReports:(NSArray*) reports
- (void) filterReports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion) onCompletion
{
NSMutableArray* filteredReports = [NSMutableArray arrayWithCapacity:[reports count]];
for(NSDictionary* report in reports)
NSMutableArray<KSCrashReport*>* filteredReports = [NSMutableArray arrayWithCapacity:[reports count]];
for(KSCrashReport* report in reports)
{
NSDictionary *reportDict = report.dictionaryValue;
if(reportDict == nil)
{
KSLOG_ERROR(@"Unexpected non-dictionary report: %@", report);
continue;
}

NSMutableDictionary* subset = [NSMutableDictionary dictionary];
for(NSString* keyPath in self.keyPaths)
{
id object = [report objectForKeyPath:keyPath];
id object = [reportDict objectForKeyPath:keyPath];
if(object == nil)
{
kscrash_callCompletion(onCompletion, filteredReports, NO,
Expand All @@ -573,7 +517,8 @@ - (void) filterReports:(NSArray*) reports
}
[subset setObject:object forKey:[keyPath lastPathComponent]];
}
[filteredReports addObject:subset];
KSCrashReport *subsetReport = [KSCrashReport reportWithDictionary:subset];
[filteredReports addObject:subsetReport];
}
kscrash_callCompletion(onCompletion, filteredReports, YES, nil);
}
Expand All @@ -588,14 +533,21 @@ + (instancetype) filter
return [[self alloc] init];
}

- (void) filterReports:(NSArray*) reports
- (void) filterReports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion)onCompletion
{
NSMutableArray* filteredReports = [NSMutableArray arrayWithCapacity:[reports count]];
for(NSData* report in reports)
NSMutableArray<KSCrashReport*>* filteredReports = [NSMutableArray arrayWithCapacity:[reports count]];
for(KSCrashReport* report in reports)
{
NSString* converted = [[NSString alloc] initWithData:report encoding:NSUTF8StringEncoding];
[filteredReports addObject:converted];
NSData* data = report.dataValue;
if(data == nil)
{
KSLOG_ERROR(@"Unexpected non-data report: %@", report);
continue;
}

NSString* converted = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[filteredReports addObject:[KSCrashReport reportWithString:converted]];
}

kscrash_callCompletion(onCompletion, filteredReports, YES, nil);
Expand All @@ -611,13 +563,20 @@ + (instancetype) filter
return [[self alloc] init];
}

- (void) filterReports:(NSArray*) reports
- (void) filterReports:(NSArray<KSCrashReport*>*) reports
onCompletion:(KSCrashReportFilterCompletion)onCompletion
{
NSMutableArray* filteredReports = [NSMutableArray arrayWithCapacity:[reports count]];
for(NSString* report in reports)
NSMutableArray<KSCrashReport*>* filteredReports = [NSMutableArray arrayWithCapacity:[reports count]];
for(KSCrashReport* report in reports)
{
NSData* converted = [report dataUsingEncoding:NSUTF8StringEncoding];
NSString* string = report.stringValue;
if(string == nil)
{
KSLOG_ERROR(@"Unexpected non-string report: %@", report);
continue;
}

NSData* converted = [string dataUsingEncoding:NSUTF8StringEncoding];
if(converted == nil)
{
kscrash_callCompletion(onCompletion, filteredReports, NO,
Expand All @@ -628,7 +587,7 @@ - (void) filterReports:(NSArray*) reports
}
else
{
[filteredReports addObject:converted];
[filteredReports addObject:[KSCrashReport reportWithData:converted]];
}
}

Expand Down
Loading

0 comments on commit 989497e

Please sign in to comment.