diff --git a/.travis.yml b/.travis.yml index 07e5bb5eb41..a2827c81adc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode8.3 +osx_image: xcode9.2 cache: - bundler diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index 12ee7e1b691..13b17a1e9b9 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -92,7 +92,7 @@ - (_Nullable instancetype)initWithDsn:(NSString *)dsn self.dsn = [[SentryDsn alloc] initWithString:dsn didFailWithError:error]; self.requestManager = requestManager; NSLog(@"Sentry Started -- Version: %@", self.class.versionString); - self.fileManager = [[SentryFileManager alloc] initWithError:error]; + self.fileManager = [[SentryFileManager alloc] initWithDsn:self.dsn didFailWithError:error]; self.breadcrumbs = [[SentryBreadcrumbStore alloc] initWithFileManager:self.fileManager]; if (nil != error && nil != *error) { [SentryLog logWithMessage:(*error).localizedDescription andLevel:kSentryLogLevelError]; diff --git a/Sources/Sentry/SentryDsn.m b/Sources/Sentry/SentryDsn.m index 42612ad2583..e84f103ea92 100644 --- a/Sources/Sentry/SentryDsn.m +++ b/Sources/Sentry/SentryDsn.m @@ -6,6 +6,8 @@ // Copyright © 2017 Sentry. All rights reserved. // +#import + #if __has_include() #import @@ -37,6 +39,17 @@ - (_Nullable instancetype)initWithString:(NSString *)dsnString didFailWithError: return self; } +- (NSString *)getHash { + NSData *data = [[self.url absoluteString] dataUsingEncoding:NSUTF8StringEncoding]; + uint8_t digest[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1(data.bytes, (CC_LONG)data.length, digest); + NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; + for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) { + [output appendFormat:@"%02x", digest[i]]; + } + return output; +} + - (NSURL *_Nullable)convertDsnString:(NSString *)dsnString didFailWithError:(NSError *_Nullable *_Nullable)error { NSString *trimmedDsnString = [dsnString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; NSSet *allowedSchemes = [NSSet setWithObjects:@"http", @"https", nil]; diff --git a/Sources/Sentry/SentryFileManager.m b/Sources/Sentry/SentryFileManager.m index bb79e69f9b7..c935e3cd748 100644 --- a/Sources/Sentry/SentryFileManager.m +++ b/Sources/Sentry/SentryFileManager.m @@ -13,6 +13,7 @@ #import #import #import +#import #else #import "SentryFileManager.h" @@ -20,6 +21,7 @@ #import "SentryLog.h" #import "SentryEvent.h" #import "SentryBreadcrumb.h" +#import "SentryDsn.h" #endif NS_ASSUME_NONNULL_BEGIN @@ -35,12 +37,15 @@ @interface SentryFileManager () @implementation SentryFileManager -- (_Nullable instancetype)initWithError:(NSError **)error { +- (_Nullable instancetype)initWithDsn:(SentryDsn *)dsn didFailWithError:(NSError **)error { self = [super init]; if (self) { NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject; + self.sentryPath = [cachePath stringByAppendingPathComponent:@"io.sentry"]; + self.sentryPath = [self.sentryPath stringByAppendingPathComponent:[dsn getHash]]; + if (![fileManager fileExistsAtPath:self.sentryPath]) { [self.class createDirectoryAtPath:self.sentryPath withError:error]; } diff --git a/Sources/Sentry/include/SentryDsn.h b/Sources/Sentry/include/SentryDsn.h index a7836cc2c3c..4d3c0582753 100644 --- a/Sources/Sentry/include/SentryDsn.h +++ b/Sources/Sentry/include/SentryDsn.h @@ -16,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN - (_Nullable instancetype)initWithString:(NSString *)dsnString didFailWithError:(NSError *_Nullable *_Nullable)error; +- (NSString *)getHash; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryFileManager.h b/Sources/Sentry/include/SentryFileManager.h index 1df5059e1a6..d5d1be3e05e 100644 --- a/Sources/Sentry/include/SentryFileManager.h +++ b/Sources/Sentry/include/SentryFileManager.h @@ -16,12 +16,12 @@ NS_ASSUME_NONNULL_BEGIN -@class SentryEvent, SentryBreadcrumb; +@class SentryEvent, SentryBreadcrumb, SentryDsn; @interface SentryFileManager : NSObject SENTRY_NO_INIT -- (_Nullable instancetype)initWithError:(NSError **)error; +- (_Nullable instancetype)initWithDsn:(SentryDsn *)dsn didFailWithError:(NSError **)error; - (NSString *)storeEvent:(SentryEvent *)event; diff --git a/Tests/SentryTests/SentryBreadcrumbTests.m b/Tests/SentryTests/SentryBreadcrumbTests.m index d932e6b5a98..68918a5fbed 100644 --- a/Tests/SentryTests/SentryBreadcrumbTests.m +++ b/Tests/SentryTests/SentryBreadcrumbTests.m @@ -11,6 +11,7 @@ #import "SentryBreadcrumbStore.h" #import "SentryFileManager.h" #import "NSDate+Extras.h" +#import "SentryDsn.h" @interface SentryBreadcrumbTests : XCTestCase @@ -23,7 +24,7 @@ @implementation SentryBreadcrumbTests - (void)setUp { [super setUp]; NSError *error = nil; - self.fileManager = [[SentryFileManager alloc] initWithError:&error]; + self.fileManager = [[SentryFileManager alloc] initWithDsn:[[SentryDsn alloc] initWithString:@"https://username:password@app.getsentry.com/12345" didFailWithError:nil] didFailWithError:&error]; XCTAssertNil(error); } diff --git a/Tests/SentryTests/SentryFileManagerTests.m b/Tests/SentryTests/SentryFileManagerTests.m index bc3abb487d5..5c99eabe0f8 100644 --- a/Tests/SentryTests/SentryFileManagerTests.m +++ b/Tests/SentryTests/SentryFileManagerTests.m @@ -9,6 +9,7 @@ #import #import #import "SentryFileManager.h" +#import "SentryDsn.h" @interface SentryFileManagerTests : XCTestCase @@ -22,7 +23,7 @@ - (void)setUp { [super setUp]; SentryClient.logLevel = kSentryLogLevelDebug; NSError *error = nil; - self.fileManager = [[SentryFileManager alloc] initWithError:&error]; + self.fileManager = [[SentryFileManager alloc] initWithDsn:[[SentryDsn alloc] initWithString:@"https://username:password@app.getsentry.com/12345" didFailWithError:nil] didFailWithError:&error]; XCTAssertNil(error); } diff --git a/Tests/SentryTests/SentryInterfacesTests.m b/Tests/SentryTests/SentryInterfacesTests.m index 63b26cf1cb7..6f6469350f9 100644 --- a/Tests/SentryTests/SentryInterfacesTests.m +++ b/Tests/SentryTests/SentryInterfacesTests.m @@ -274,7 +274,7 @@ - (void)testBreadcrumb { } - (void)testBreadcrumbStore { - SentryBreadcrumbStore *store = [[SentryBreadcrumbStore alloc] initWithFileManager:[[SentryFileManager alloc] initWithError:nil]]; + SentryBreadcrumbStore *store = [[SentryBreadcrumbStore alloc] initWithFileManager:[[SentryFileManager alloc] initWithDsn:[[SentryDsn alloc] initWithString:@"https://username:password@app.getsentry.com/12345" didFailWithError:nil] didFailWithError:nil]]; SentryBreadcrumb *crumb = [[SentryBreadcrumb alloc] initWithLevel:kSentrySeverityInfo category:@"http"]; [store addBreadcrumb:crumb]; NSDate *date = [NSDate date]; diff --git a/Tests/SentryTests/SentryJavaScriptBridgeHelperTests.m b/Tests/SentryTests/SentryJavaScriptBridgeHelperTests.m index 5b989c5e566..f2e79dba21d 100644 --- a/Tests/SentryTests/SentryJavaScriptBridgeHelperTests.m +++ b/Tests/SentryTests/SentryJavaScriptBridgeHelperTests.m @@ -10,6 +10,8 @@ #import "SentryJavaScriptBridgeHelper.h" #import +NSString *rnReportPath = @""; + @interface SentryJavaScriptBridgeHelper() + (NSArray *)parseJavaScriptStacktrace:(NSString *)stacktrace; @@ -109,14 +111,22 @@ - (void)testCreateBreadcrumb { XCTAssertTrue([crumb2.timestamp compare:date]); } +- (NSDictionary *)getCrashReport { + NSString *jsonPath = [[NSBundle bundleForClass:self.class] pathForResource:rnReportPath ofType:@"json"]; + NSData *jsonData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:jsonPath]]; + return [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil]; +} + - (void)testCreateEvent { - SentryEvent *sentryEvent1 = [SentryJavaScriptBridgeHelper createSentryEventFromJavaScriptEvent:[NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle bundleForClass:self.class] pathForResource:@"raven-sendMessage" ofType:@"json"]]] options:0 error:nil]]; + rnReportPath = @"Resources/raven-sendMessage"; + SentryEvent *sentryEvent1 = [SentryJavaScriptBridgeHelper createSentryEventFromJavaScriptEvent:[self getCrashReport]]; XCTAssertEqualObjects(sentryEvent1.message, @"TEST message"); XCTAssertNotNil(sentryEvent1.extra); XCTAssertNotNil(sentryEvent1.tags); XCTAssertNotNil(sentryEvent1.user); - SentryEvent *sentryEvent2 = [SentryJavaScriptBridgeHelper createSentryEventFromJavaScriptEvent:[NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle bundleForClass:self.class] pathForResource:@"raven-rejectedpromise" ofType:@"json"]]] options:0 error:nil]]; + rnReportPath = @"Resources/raven-rejectedpromise"; + SentryEvent *sentryEvent2 = [SentryJavaScriptBridgeHelper createSentryEventFromJavaScriptEvent:[self getCrashReport]]; XCTAssertEqualObjects(sentryEvent2.message, @"Boom promise"); XCTAssertEqualObjects(sentryEvent2.platform, @"cocoa"); XCTAssertEqualObjects(sentryEvent2.exceptions.firstObject.type, @"Unhandled Promise Rejection"); @@ -127,7 +137,8 @@ - (void)testCreateEvent { XCTAssertNotNil(sentryEvent2.tags); XCTAssertNotNil(sentryEvent2.user); - SentryEvent *sentryEvent3 = [SentryJavaScriptBridgeHelper createSentryEventFromJavaScriptEvent:[NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle bundleForClass:self.class] pathForResource:@"raven-throwerror" ofType:@"json"]]] options:0 error:nil]]; + rnReportPath = @"Resources/raven-throwerror"; + SentryEvent *sentryEvent3 = [SentryJavaScriptBridgeHelper createSentryEventFromJavaScriptEvent:[self getCrashReport]]; XCTAssertEqualObjects(sentryEvent3.exceptions.firstObject.value, @"Sentry: Test throw error"); XCTAssertEqualObjects(sentryEvent3.exceptions.firstObject.type, @"Error"); XCTAssertEqual(sentryEvent3.exceptions.firstObject.thread.stacktrace.frames.count, (NSUInteger)30); diff --git a/Tests/SentryTests/SentryRequestTests.m b/Tests/SentryTests/SentryRequestTests.m index 7aec8e89b29..c0f0625452d 100644 --- a/Tests/SentryTests/SentryRequestTests.m +++ b/Tests/SentryTests/SentryRequestTests.m @@ -156,7 +156,7 @@ @implementation SentryRequestTests - (void)clearAllFiles { NSError *error = nil; - SentryFileManager *fileManager = [[SentryFileManager alloc] initWithError:&error]; + SentryFileManager *fileManager = [[SentryFileManager alloc] initWithDsn:[[SentryDsn alloc] initWithString:@"https://username:password@app.getsentry.com/12345" didFailWithError:nil] didFailWithError:&error]; [fileManager deleteAllStoredEvents]; [fileManager deleteAllStoredBreadcrumbs]; [fileManager deleteAllFolders]; diff --git a/Tests/SentryTests/SentrySwiftTests.swift b/Tests/SentryTests/SentrySwiftTests.swift index 2660530904b..5d6a09e2058 100644 --- a/Tests/SentryTests/SentrySwiftTests.swift +++ b/Tests/SentryTests/SentrySwiftTests.swift @@ -13,7 +13,7 @@ class SentrySwiftTests: XCTestCase { override func setUp() { super.setUp() - let fileManager = try! SentryFileManager(error: ()) + let fileManager = try! SentryFileManager(dsn: SentryDsn(string: "https://username:password@app.getsentry.com/12345")) fileManager.deleteAllStoredEvents() fileManager.deleteAllStoredBreadcrumbs() fileManager.deleteAllFolders() diff --git a/Tests/SentryTests/SentryTests.m b/Tests/SentryTests/SentryTests.m index ba743df00d3..703abe670ad 100644 --- a/Tests/SentryTests/SentryTests.m +++ b/Tests/SentryTests/SentryTests.m @@ -54,13 +54,15 @@ - (void)testCrashedLastLaunch { - (void)testBreadCrumbTracking { NSError *error = nil; - SentryClient *client = [[SentryClient alloc] initWithDsn:@"https://username:password@app.getsentry.com/12345" didFailWithError:&error]; + SentryClient *client = [[SentryClient alloc] initWithDsn:@"https://username:password@app.getsentry.com/123456" didFailWithError:&error]; + [client.breadcrumbs clear]; [client enableAutomaticBreadcrumbTracking]; XCTAssertEqual(client.breadcrumbs.count, (unsigned long)0); [SentryClient setSharedClient:client]; [SentryClient.sharedClient enableAutomaticBreadcrumbTracking]; XCTAssertEqual(SentryClient.sharedClient.breadcrumbs.count, (unsigned long)1); [SentryClient setSharedClient:nil]; + [client.breadcrumbs clear]; } - (void)testInstallation {