From 720b57bafcb5a94a68ad0cfd58929e84d7d04daa Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 19 Apr 2021 11:35:30 +0200 Subject: [PATCH 01/48] Change transport api to envelope only --- CHANGELOG.md | 2 +- dart/lib/src/sentry_client.dart | 5 +-- dart/lib/src/transport/http_transport.dart | 10 ++---- dart/lib/src/transport/noop_transport.dart | 6 +--- dart/lib/src/transport/transport.dart | 3 +- dart/test/mocks/mock_transport.dart | 11 ++----- dart/test/transport/http_transport_test.dart | 14 ++++++--- flutter/lib/src/file_system_transport.dart | 8 +---- flutter/test/file_system_transport_test.dart | 16 ++++++++-- flutter/test/mocks.mocks.dart | 27 +++++++--------- flutter/test/sentry_flutter_test.dart | 33 ++++++++++---------- 11 files changed, 61 insertions(+), 74 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f47d2ee4d..35ef79abe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ ## Breaking Changes: * Feat: Support envelope based transport for events (#391) - * The method signature of `Transport` changed from `Future send(SentryEvent event)` to `Future sendSentryEvent(SentryEvent event)` + * The method signature of `Transport` changed from `Future send(SentryEvent event)` to `Future send(SentryEnvelope envelope)` ## Sentry Self Hosted Compatibility diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index 6e865c4ab7..82aab6e601 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -106,7 +106,8 @@ class SentryClient { return _sentryId; } } - return await _options.transport.sendSentryEvent(preparedEvent); + final envelope = SentryEnvelope.fromEvent(preparedEvent, _options.sdk); + return await _options.transport.send(envelope); } SentryEvent _prepareEvent(SentryEvent event, {dynamic stackTrace}) { @@ -199,7 +200,7 @@ class SentryClient { /// Reports the [envelope] to Sentry.io. Future captureEnvelope(SentryEnvelope envelope) { - return _options.transport.sendSentryEnvelope(envelope); + return _options.transport.send(envelope); } void close() => _options.httpClient.close(); diff --git a/dart/lib/src/transport/http_transport.dart b/dart/lib/src/transport/http_transport.dart index d54ed8a4c2..28100a4d6e 100644 --- a/dart/lib/src/transport/http_transport.dart +++ b/dart/lib/src/transport/http_transport.dart @@ -42,15 +42,9 @@ class HttpTransport implements Transport { _options.clock, ); } - - @override - Future sendSentryEvent(SentryEvent event) async { - final envelope = SentryEnvelope.fromEvent(event, _options.sdk); - return await sendSentryEnvelope(envelope); - } - + @override - Future sendSentryEnvelope(SentryEnvelope envelope) async { + Future send(SentryEnvelope envelope) async { final filteredEnvelope = _rateLimiter.filter(envelope); if (filteredEnvelope == null) { return SentryId.empty(); diff --git a/dart/lib/src/transport/noop_transport.dart b/dart/lib/src/transport/noop_transport.dart index 0e36b14d0d..705dfc3a9c 100644 --- a/dart/lib/src/transport/noop_transport.dart +++ b/dart/lib/src/transport/noop_transport.dart @@ -7,10 +7,6 @@ import 'transport.dart'; class NoOpTransport implements Transport { @override - Future sendSentryEvent(SentryEvent event) => - Future.value(SentryId.empty()); - - @override - Future sendSentryEnvelope(SentryEnvelope envelope) => + Future send(SentryEnvelope envelope) => Future.value(SentryId.empty()); } diff --git a/dart/lib/src/transport/transport.dart b/dart/lib/src/transport/transport.dart index ca1e05cfd9..08de9e9322 100644 --- a/dart/lib/src/transport/transport.dart +++ b/dart/lib/src/transport/transport.dart @@ -6,6 +6,5 @@ import '../protocol.dart'; /// A transport is in charge of sending the event/envelope either via http /// or caching in the disk. abstract class Transport { - Future sendSentryEvent(SentryEvent event); - Future sendSentryEnvelope(SentryEnvelope envelope); + Future send(SentryEnvelope envelope); } diff --git a/dart/test/mocks/mock_transport.dart b/dart/test/mocks/mock_transport.dart index cb5d4f43f7..64ed6902c5 100644 --- a/dart/test/mocks/mock_transport.dart +++ b/dart/test/mocks/mock_transport.dart @@ -1,21 +1,14 @@ import 'package:sentry/sentry.dart'; class MockTransport implements Transport { - List events = []; List envelopes = []; bool called(int calls) { - return events.length == calls; + return envelopes.length == calls; } @override - Future sendSentryEvent(SentryEvent event) async { - events.add(event); - return event.eventId; - } - - @override - Future sendSentryEnvelope(SentryEnvelope envelope) async { + Future send(SentryEnvelope envelope) async { envelopes.add(envelope); return envelope.header.eventId ?? SentryId.empty(); } diff --git a/dart/test/transport/http_transport_test.dart b/dart/test/transport/http_transport_test.dart index bc3867bba0..ac085dee56 100644 --- a/dart/test/transport/http_transport_test.dart +++ b/dart/test/transport/http_transport_test.dart @@ -43,7 +43,7 @@ void main() { final sut = HttpTransport(options, mockRateLimiter); final sentryEnvelope = givenEnvelope(); - await sut.sendSentryEnvelope(sentryEnvelope); + await sut.send(sentryEnvelope); expect(mockRateLimiter.envelopeToFilter, sentryEnvelope); }); @@ -68,7 +68,8 @@ void main() { final sut = HttpTransport(options, mockRateLimiter); final sentryEvent = SentryEvent(); - await sut.sendSentryEvent(sentryEvent); + final envelope = SentryEnvelope.fromEvent(sentryEvent, options.sdk); + await sut.send(envelope); final envelopeData = []; await filteredEnvelope.envelopeStream().forEach(envelopeData.addAll); @@ -94,7 +95,8 @@ void main() { final sut = HttpTransport(options, mockRateLimiter); final sentryEvent = SentryEvent(); - final eventId = await sut.sendSentryEvent(sentryEvent); + final envelope = SentryEnvelope.fromEvent(sentryEvent, options.sdk); + final eventId = await sut.send(envelope); expect(eventId, SentryId.empty()); expect(httpCalled, false); @@ -115,7 +117,8 @@ void main() { final sut = HttpTransport(options, mockRateLimiter); final sentryEvent = SentryEvent(); - await sut.sendSentryEvent(sentryEvent); + final envelope = SentryEnvelope.fromEvent(sentryEvent, options.sdk); + await sut.send(envelope); expect(mockRateLimiter.envelopeToFilter?.header.eventId, sentryEvent.eventId); @@ -139,7 +142,8 @@ void main() { final sut = HttpTransport(options, mockRateLimiter); final sentryEvent = SentryEvent(); - await sut.sendSentryEvent(sentryEvent); + final envelope = SentryEnvelope.fromEvent(sentryEvent, options.sdk); + await sut.send(envelope); expect(mockRateLimiter.errorCode, 200); expect(mockRateLimiter.retryAfterHeader, isNull); diff --git a/flutter/lib/src/file_system_transport.dart b/flutter/lib/src/file_system_transport.dart index eb718d93f5..844e2de383 100644 --- a/flutter/lib/src/file_system_transport.dart +++ b/flutter/lib/src/file_system_transport.dart @@ -10,13 +10,7 @@ class FileSystemTransport implements Transport { final SentryOptions _options; @override - Future sendSentryEvent(SentryEvent event) async { - final envelope = SentryEnvelope.fromEvent(event, _options.sdk); - return await sendSentryEnvelope(envelope); - } - - @override - Future sendSentryEnvelope(SentryEnvelope envelope) async { + Future send(SentryEnvelope envelope) async { final envelopeData = []; await envelope.envelopeStream().forEach(envelopeData.addAll); diff --git a/flutter/test/file_system_transport_test.dart b/flutter/test/file_system_transport_test.dart index 6a0f7fe511..f01612fd98 100644 --- a/flutter/test/file_system_transport_test.dart +++ b/flutter/test/file_system_transport_test.dart @@ -25,8 +25,11 @@ void main() { final transport = fixture.getSut(_channel); final event = SentryEvent(); + final sdkVersion = + SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); - final sentryId = await transport.sendSentryEvent(event); + final envelope = SentryEnvelope.fromEvent(event, sdkVersion); + final sentryId = await transport.send(envelope); expect(sentryId, sentryId); }); @@ -37,8 +40,12 @@ void main() { }); final transport = fixture.getSut(_channel); + final event = SentryEvent(); + final sdkVersion = + SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); - final sentryId = await transport.sendSentryEvent(SentryEvent()); + final envelope = SentryEnvelope.fromEvent(event, sdkVersion); + final sentryId = await transport.send(envelope); expect(SentryId.empty(), sentryId); }); @@ -53,7 +60,10 @@ void main() { final event = SentryEvent(message: SentryMessage('hi I am a special char ◤')); - await transport.sendSentryEvent(event); + final sdkVersion = + SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); + final envelope = SentryEnvelope.fromEvent(event, sdkVersion); + await transport.send(envelope); final envelopeList = arguments as List; final envelopeString = envelopeList.first as String; diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index 445b4056ca..a4273b0b5c 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.0.3 from annotations +// Mocks generated by Mockito 5.0.4 from annotations // in sentry_flutter/example/ios/.symlinks/plugins/sentry_flutter/test/mocks.dart. // Do not manually edit this file. @@ -41,17 +41,17 @@ class MockHub extends _i1.Mock implements _i3.Hub { _i4.Future<_i2.SentryId> captureEvent(_i5.SentryEvent? event, {dynamic stackTrace, dynamic hint}) => (super.noSuchMethod( - Invocation.method( - #captureEvent, [event], {#stackTrace: stackTrace, #hint: hint}), - returnValue: - Future.value(_FakeSentryId())) as _i4.Future<_i2.SentryId>); + Invocation.method(#captureEvent, [event], + {#stackTrace: stackTrace, #hint: hint}), + returnValue: Future<_i2.SentryId>.value(_FakeSentryId())) + as _i4.Future<_i2.SentryId>); @override _i4.Future<_i2.SentryId> captureException(dynamic throwable, {dynamic stackTrace, dynamic hint}) => (super.noSuchMethod( Invocation.method(#captureException, [throwable], {#stackTrace: stackTrace, #hint: hint}), - returnValue: Future.value(_FakeSentryId())) + returnValue: Future<_i2.SentryId>.value(_FakeSentryId())) as _i4.Future<_i2.SentryId>); @override _i4.Future<_i2.SentryId> captureMessage(String? message, @@ -68,7 +68,7 @@ class MockHub extends _i1.Mock implements _i3.Hub { #params: params, #hint: hint }), - returnValue: Future.value(_FakeSentryId())) + returnValue: Future<_i2.SentryId>.value(_FakeSentryId())) as _i4.Future<_i2.SentryId>); @override void addBreadcrumb(_i7.Breadcrumb? crumb, {dynamic hint}) => super @@ -83,7 +83,7 @@ class MockHub extends _i1.Mock implements _i3.Hub { returnValue: _FakeHub()) as _i3.Hub); @override _i4.Future close() => (super.noSuchMethod(Invocation.method(#close, []), - returnValue: Future.value(null), + returnValue: Future.value(null), returnValueForMissingStub: Future.value()) as _i4.Future); @override void configureScope(_i3.ScopeCallback? callback) => @@ -100,13 +100,8 @@ class MockTransport extends _i1.Mock implements _i9.Transport { } @override - _i4.Future<_i2.SentryId> sendSentryEvent(_i5.SentryEvent? event) => - (super.noSuchMethod(Invocation.method(#sendSentryEvent, [event]), - returnValue: Future.value(_FakeSentryId())) - as _i4.Future<_i2.SentryId>); - @override - _i4.Future<_i2.SentryId> sendSentryEnvelope(_i10.SentryEnvelope? envelope) => - (super.noSuchMethod(Invocation.method(#sendSentryEnvelope, [envelope]), - returnValue: Future.value(_FakeSentryId())) + _i4.Future<_i2.SentryId> send(_i10.SentryEnvelope? envelope) => + (super.noSuchMethod(Invocation.method(#send, [envelope]), + returnValue: Future<_i2.SentryId>.value(_FakeSentryId())) as _i4.Future<_i2.SentryId>); } diff --git a/flutter/test/sentry_flutter_test.dart b/flutter/test/sentry_flutter_test.dart index cf48690dfd..138c6c3d2f 100644 --- a/flutter/test/sentry_flutter_test.dart +++ b/flutter/test/sentry_flutter_test.dart @@ -52,7 +52,7 @@ void main() { _channel.setMockMethodCallHandler( (MethodCall methodCall) async => {}, ); - when(transport.sendSentryEvent(any)) + when(transport.send(any)) .thenAnswer((realInvocation) => Future.value(SentryId.newId())); }); @@ -73,11 +73,11 @@ void main() { await Sentry.captureMessage('a message'); - final event = verify(transport.sendSentryEvent(captureAny)).captured.first - as SentryEvent; + final envelope = verify(transport.send(captureAny)).captured.first + as SentryEnvelope; - expect(event.sdk!.integrations.length, 7); - expect(event.sdk!.integrations.contains('loadContextsIntegration'), true); + // expect(event.sdk!.integrations.length, 7); + // expect(event.sdk!.integrations.contains('loadContextsIntegration'), true); }); test('should not add loadContextsIntegration if not ios', () async { @@ -92,12 +92,13 @@ void main() { await Sentry.captureMessage('a message'); - final event = verify(transport.sendSentryEvent(captureAny)).captured.first - as SentryEvent; + final envelope = verify(transport.send(captureAny)).captured.first + as SentryEnvelope; - expect(event.sdk!.integrations.length, 6); - expect( - event.sdk!.integrations.contains('loadContextsIntegration'), false); + // TODO + // expect(event.sdk!.integrations.length, 6); + // expect( + // event.sdk!.integrations.contains('loadContextsIntegration'), false); }); test('should not add loadAndroidImageListIntegration if not Android', @@ -113,13 +114,13 @@ void main() { await Sentry.captureMessage('a message'); - final event = verify(transport.sendSentryEvent(captureAny)).captured.first - as SentryEvent; + final envelope = verify(transport.send(captureAny)).captured.first + as SentryEnvelope; - expect(event.sdk!.integrations.length, 6); - expect( - event.sdk!.integrations.contains('loadAndroidImageListIntegration'), - false); + // expect(event.sdk!.integrations.length, 6); + // expect( + // event.sdk!.integrations.contains('loadAndroidImageListIntegration'), + // false); }); }); } From 3009e0936aa4ae67192479000f7edbfda16fe090 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 09:51:44 +0200 Subject: [PATCH 02/48] First step to fix tests by derializing from json --- dart/lib/src/protocol/breadcrumb.dart | 12 ++ dart/lib/src/protocol/contexts.dart | 2 +- dart/lib/src/protocol/sdk_version.dart | 12 ++ dart/lib/src/protocol/sentry_event.dart | 80 +++++++++++ dart/lib/src/protocol/sentry_exception.dart | 12 ++ dart/lib/src/protocol/sentry_level.dart | 14 ++ dart/lib/src/protocol/sentry_message.dart | 8 ++ dart/lib/src/protocol/sentry_package.dart | 7 + dart/lib/src/protocol/sentry_stack_frame.dart | 24 ++++ dart/lib/src/protocol/sentry_stack_trace.dart | 11 ++ dart/lib/src/protocol/sentry_user.dart | 10 ++ dart/test/sentry_client_test.dart | 132 +++++++++++++----- 12 files changed, 288 insertions(+), 36 deletions(-) diff --git a/dart/lib/src/protocol/breadcrumb.dart b/dart/lib/src/protocol/breadcrumb.dart index cd3700d9b5..ec55e699e3 100644 --- a/dart/lib/src/protocol/breadcrumb.dart +++ b/dart/lib/src/protocol/breadcrumb.dart @@ -76,6 +76,18 @@ class Breadcrumb { /// The value is submitted to Sentry with second precision. final DateTime timestamp; + factory Breadcrumb.fromJson(Map json) { + final levelName = json['level']?.toString(); + return Breadcrumb( + timestamp: DateTime.now(), // TODO + message: json['message']?.toString(), + category: json['category']?.toString(), + data: json['data'] as Map?, + level: levelName != null ? SentryLevel.fromName(levelName) : null, + type: json['type']?.toString(), + ); + } + /// Converts this breadcrumb to a map that can be serialized to JSON according /// to the Sentry protocol. Map toJson() { diff --git a/dart/lib/src/protocol/contexts.dart b/dart/lib/src/protocol/contexts.dart index a1205e9650..4bd5055c8b 100644 --- a/dart/lib/src/protocol/contexts.dart +++ b/dart/lib/src/protocol/contexts.dart @@ -103,7 +103,7 @@ class Contexts extends MapView { SentryGpu? get gpu => this[SentryGpu.type]; set gpu(SentryGpu? gpu) => this[SentryGpu.type] = gpu; - + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sdk_version.dart b/dart/lib/src/protocol/sdk_version.dart index dc4a7c9ad3..3395032fc2 100644 --- a/dart/lib/src/protocol/sdk_version.dart +++ b/dart/lib/src/protocol/sdk_version.dart @@ -63,6 +63,18 @@ class SdkVersion { String get identifier => '$name/$version'; + /// Produces a [SdkVersion] from deserialiazed JSON [Map]. + factory SdkVersion.fromJson(Map json) { + final packagesJson = json['packages'] as List?; + final integrationsJson = json['integrations'] as List?; + return SdkVersion( + name: json['name'].toString(), + version: json['version'].toString(), + packages: packagesJson?.map((e) => SentryPackage.fromJson(e as Map)).toList(), + integrations: integrationsJson?.map((e) => e as String).toList() + ); + } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 7472ce1950..fabfe8ed16 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -226,6 +226,86 @@ class SentryEvent { debugMeta: debugMeta ?? this.debugMeta, ); + factory SentryEvent.fromJson(Map json) { + final breadcrumbsJson = json['breadcrumbs'] as List?; + final breadcrumbs = breadcrumbsJson?.map((e) { + return Breadcrumb.fromJson(e); + }).toList(); + + final sdkJson = json['sdk'] as Map?; + final messageJson = json['message'] as Map?; + + final stackTraceJson = json['threads'] as Map?; + final stackTraceValuesJson = stackTraceJson?['values'] as List?; + Map? stackTraceValuesStacktraceJson; + if (stackTraceValuesJson?.isNotEmpty == true) { + stackTraceValuesStacktraceJson = + stackTraceValuesJson?.first['stacktrace'] as Map?; + } + + final exceptionJson = json['exception'] as Map?; + final exceptionValuesJson = exceptionJson?['values'] as List?; + final exceptionValuesItemJson = + exceptionValuesJson?.first as Map?; + + final levelName = json['level']?.toString(); + + final userJson = json['user'] as Map?; + + final fingerprintJson = json['fingerprint'] as List?; + + final modulesJson = json['modules'] as Map?; + Map? modules; + if (modulesJson != null) { + modules = {}; + modulesJson.forEach((key, value) { + modules?[key] = value as String; + }); + } + + final tagsJson = json['tags'] as Map?; + Map? tags; + if (tagsJson != null) { + tags = {}; + tagsJson.forEach((key, value) { + tags?[key] = value as String; + }); + } + + return SentryEvent( + eventId: SentryId.fromId(['event_id'].toString()), // TODO: Hanled '-'? + timestamp: DateTime.now(), // TODO: Parse timestamp + modules: modules, + tags: tags, + extra: json['extra'] as Map?, + fingerprint: fingerprintJson != null + ? fingerprintJson.map((e) => e as String).toList() + : null, + breadcrumbs: breadcrumbs, + sdk: sdkJson != null ? SdkVersion.fromJson(sdkJson) : null, + platform: json['platform']?.toString(), + logger: json['logger']?.toString(), + serverName: json['server_name']?.toString(), + release: json['release']?.toString(), + dist: json['dist']?.toString(), + environment: json['environment']?.toString(), + message: messageJson != null ? SentryMessage.fromJson(messageJson) : null, + transaction: json['transaction']?.toString(), + stackTrace: stackTraceValuesStacktraceJson != null + ? SentryStackTrace.fromJson(stackTraceValuesStacktraceJson) + : null, + exception: exceptionValuesItemJson != null + ? SentryException.fromJson(exceptionValuesItemJson) + : null, + level: levelName != null ? SentryLevel.fromName(levelName) : null, + culprit: json['culprit']?.toString(), + user: userJson != null ? SentryUser.fromJson(userJson) : null, + contexts: null, // TODO(denis) + request: null, // TODO(denis) + debugMeta: null, // TODO(denis) + ); + } + /// Serializes this event to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_exception.dart b/dart/lib/src/protocol/sentry_exception.dart index c4d2558240..76b0bfd5d2 100644 --- a/dart/lib/src/protocol/sentry_exception.dart +++ b/dart/lib/src/protocol/sentry_exception.dart @@ -32,6 +32,18 @@ class SentryException { this.threadId, }); + factory SentryException.fromJson(Map json) { + final stackTraceJson = json['stacktrace'] as Map?; + return SentryException( + type: json['type']?.toString(), + value: json['value']?.toString(), + module: json['module']?.toString(), + stackTrace: stackTraceJson != null + ? SentryStackTrace.fromJson(stackTraceJson) + : null + ); + } + Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_level.dart b/dart/lib/src/protocol/sentry_level.dart index a0e59e32fc..6be45655fb 100644 --- a/dart/lib/src/protocol/sentry_level.dart +++ b/dart/lib/src/protocol/sentry_level.dart @@ -14,4 +14,18 @@ class SentryLevel { /// API name of the level as it is encoded in the JSON protocol. final String name; final int ordinal; + + factory SentryLevel.fromName(String name) { + if (name == 'fatal') { + return SentryLevel.fatal; + } else if (name == 'error') { + return SentryLevel.error; + } else if (name == 'warning') { + return SentryLevel.warning; + } else if (name == 'info') { + return SentryLevel.info; + } else { + return SentryLevel.debug; + } + } } diff --git a/dart/lib/src/protocol/sentry_message.dart b/dart/lib/src/protocol/sentry_message.dart index 3842e35b1d..b8f9058fba 100644 --- a/dart/lib/src/protocol/sentry_message.dart +++ b/dart/lib/src/protocol/sentry_message.dart @@ -22,6 +22,14 @@ class SentryMessage { const SentryMessage(this.formatted, {this.template, this.params}); + factory SentryMessage.fromJson(Map json) { + return SentryMessage( + json['formatted'].toString(), + template: json['message']?.toString(), + params: json['params'] as List? + ); + } + Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_package.dart b/dart/lib/src/protocol/sentry_package.dart index 57e5e4a9f4..52a67cabbf 100644 --- a/dart/lib/src/protocol/sentry_package.dart +++ b/dart/lib/src/protocol/sentry_package.dart @@ -12,6 +12,13 @@ class SentryPackage { /// The version of the SDK. final String version; + factory SentryPackage.fromJson(Map json) { + return SentryPackage( + json['name'].toString(), + json['version'].toString(), + ); + } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { return { diff --git a/dart/lib/src/protocol/sentry_stack_frame.dart b/dart/lib/src/protocol/sentry_stack_frame.dart index 685cac4df2..9a5fd0279b 100644 --- a/dart/lib/src/protocol/sentry_stack_frame.dart +++ b/dart/lib/src/protocol/sentry_stack_frame.dart @@ -108,6 +108,30 @@ class SentryStackFrame { /// The original function name, if the function name is shortened or demangled. Sentry shows the raw function when clicking on the shortened one in the UI. final String? rawFunction; + factory SentryStackFrame.fromJson(Map json) { + return SentryStackFrame( + absPath: json['abs_path']?.toString(), + fileName: json['filename']?.toString(), + function: json['function']?.toString(), + module: json['module']?.toString(), + lineNo: json['lineno'] as int?, + colNo: json['colno'] as int?, + contextLine: json['context_line']?.toString(), + inApp: json['in_app'] as bool?, + package: json['package']?.toString(), + native: json['native'] as bool?, + platform: json['platform']?.toString(), + imageAddr: json['image_addr']?.toString(), + symbolAddr: json['symbol_addr']?.toString(), + instructionAddr: json['instruction_addr']?.toString(), + rawFunction: json['raw_function']?.toString(), + framesOmitted: json['raw_function'] as List?, + preContext: json['pre_context'] as List?, + postContext: json['post_context'] as List?, + vars: json['vars'] as Map?, + ); + } + Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_stack_trace.dart b/dart/lib/src/protocol/sentry_stack_trace.dart index 112ecd81c4..719e3477df 100644 --- a/dart/lib/src/protocol/sentry_stack_trace.dart +++ b/dart/lib/src/protocol/sentry_stack_trace.dart @@ -25,6 +25,17 @@ class SentryStackTrace { /// thus mapping to the last frame in the list. Map get registers => Map.unmodifiable(_registers ?? const {}); + factory SentryStackTrace.fromJson(Map json) { + final framesJson = json['frames'] as List?; + return SentryStackTrace( + frames: framesJson != null + ? framesJson + .map((frameJson) => SentryStackFrame.fromJson(frameJson)) + .toList() + : [], + registers: json['registers'] as Map?); + } + Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index 34ff14080d..993bcb9d20 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -53,6 +53,16 @@ class SentryUser { /// by Sentry. final Map? extras; + factory SentryUser.fromJson(Map json) { + return SentryUser( + id: json['id']?.toString(), + username: json['username']?.toString(), + email: json['email']?.toString(), + ipAddress: json['ip_address']?.toString(), + extras: json['extras'] as Map?, + ); + } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { return { diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 0b702b8d26..6bd26b37a4 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:sentry/sentry.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; import 'package:test/test.dart'; @@ -22,7 +24,9 @@ void main() { stackTrace: '#0 baz (file:///pathto/test.dart:50:3)', ); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.stackTrace is SentryStackTrace, true); }); @@ -32,7 +36,9 @@ void main() { final event = SentryEvent(); await client.captureEvent(event); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.stackTrace is SentryStackTrace, true); }); @@ -42,7 +48,9 @@ void main() { final event = SentryEvent(); await client.captureEvent(event); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.stackTrace, isNull); }); @@ -62,7 +70,9 @@ void main() { stackTrace: '#0 baz (file:///pathto/test.dart:50:3)', ); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.stackTrace, isNull); expect(capturedEvent.exception!.stackTrace, isNotNull); @@ -86,7 +96,9 @@ void main() { stackTrace: '#0 baz (file:///pathto/test.dart:50:3)', ); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.stackTrace, isNull); expect(capturedEvent.exception!.stackTrace, isNotNull); @@ -101,7 +113,9 @@ void main() { level: SentryLevel.error, ); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.message!.formatted, 'simple message 1'); expect(capturedEvent.message!.template, 'simple message %d'); @@ -115,7 +129,10 @@ void main() { 'simple message 1', ); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); + expect(capturedEvent.level, SentryLevel.info); }); @@ -123,7 +140,9 @@ void main() { final client = SentryClient(options..attachStacktrace = false); await client.captureMessage('message', level: SentryLevel.error); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.stackTrace, isNull); }); @@ -151,9 +170,11 @@ void main() { final client = SentryClient(options); await client.captureException(error, stackTrace: stackTrace); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); - expect(capturedEvent.throwable, error); + //expect(capturedEvent.throwable, error); // Cannot recreate insance from envelope... expect(capturedEvent.exception is SentryException, true); expect(capturedEvent.exception!.stackTrace, isNotNull); }); @@ -185,9 +206,11 @@ void main() { final client = SentryClient(options); await client.captureException(error, stackTrace: stacktrace); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); - expect(capturedEvent.throwable, error); + //expect(capturedEvent.throwable, error); // Cannot recreate insance from envelope... expect(capturedEvent.exception is SentryException, true); expect(capturedEvent.exception!.stackTrace, isNotNull); expect(capturedEvent.exception!.stackTrace!.frames.first.fileName, @@ -223,9 +246,11 @@ void main() { final client = SentryClient(options); await client.captureException(exception, stackTrace: stacktrace); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); - expect(capturedEvent.throwable, exception); + //expect(capturedEvent.throwable, exception); // Cannot recreate insance from envelope... expect(capturedEvent.exception is SentryException, true); expect(capturedEvent.exception!.stackTrace!.frames.first.fileName, 'test.dart'); @@ -243,7 +268,9 @@ void main() { final client = SentryClient(options); await client.captureException(exception); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.exception!.stackTrace, isNotNull); }); @@ -258,7 +285,9 @@ void main() { final client = SentryClient(options..attachStacktrace = false); await client.captureException(exception); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.exception!.stackTrace, isNull); }); @@ -280,7 +309,9 @@ void main() { final client = SentryClient(options); await client.captureException(exception, stackTrace: stacktrace); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect( capturedEvent.exception!.stackTrace!.frames @@ -333,7 +364,9 @@ void main() { final client = SentryClient(options); await client.captureEvent(event, scope: scope); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.user?.id, user.id); expect(capturedEvent.level!.name, SentryLevel.error.name); @@ -386,7 +419,9 @@ void main() { final client = SentryClient(options); await client.captureEvent(event, scope: scope); - final capturedEvent = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect(capturedEvent.user!.id, eventUser.id); expect(capturedEvent.level!.name, SentryLevel.warning.name); @@ -409,7 +444,10 @@ void main() { await client.captureEvent(fakeEvent); - expect(transport.events.first.user, fakeEvent.user); + final capturedEnvelope = transport.envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); + + expect(capturedEvent.user?.toJson(), fakeEvent.user?.toJson()); }); test('sendDefaultPii is enabled and event has no user', () async { @@ -419,9 +457,12 @@ void main() { await client.captureEvent(fakeEvent); - expect(transport.events.length, 1); - expect(transport.events.first.user, isNotNull); - expect(transport.events.first.user?.ipAddress, '{{auto}}'); + final capturedEnvelope = transport.envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); + + expect(transport.envelopes.length, 1); + expect(capturedEvent.user, isNotNull); + expect(capturedEvent.user?.ipAddress, '{{auto}}'); }); test('sendDefaultPii is enabled and event has a user with IP address', @@ -431,12 +472,15 @@ void main() { await client.captureEvent(fakeEvent); - expect(transport.events.length, 1); - expect(transport.events.first.user, isNotNull); + final capturedEnvelope = transport.envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); + + expect(transport.envelopes.length, 1); + expect(capturedEvent.user, isNotNull); // fakeEvent has a user which is not null - expect(transport.events.first.user?.ipAddress, fakeEvent.user!.ipAddress); - expect(transport.events.first.user?.id, fakeEvent.user!.id); - expect(transport.events.first.user?.email, fakeEvent.user!.email); + expect(capturedEvent.user?.ipAddress, fakeEvent.user!.ipAddress); + expect(capturedEvent.user?.id, fakeEvent.user!.id); + expect(capturedEvent.user?.email, fakeEvent.user!.email); }); test('sendDefaultPii is enabled and event has a user without IP address', @@ -448,11 +492,14 @@ void main() { await client.captureEvent(event); - expect(transport.events.length, 1); - expect(transport.events.first.user, isNotNull); - expect(transport.events.first.user?.ipAddress, '{{auto}}'); - expect(transport.events.first.user?.id, fakeUser.id); - expect(transport.events.first.user?.email, fakeUser.email); + final capturedEnvelope = transport.envelopes.first; + final capturedEvent = await eventFromEnvelope(capturedEnvelope); + + expect(transport.envelopes.length, 1); + expect(capturedEvent.user, isNotNull); + expect(capturedEvent.user?.ipAddress, '{{auto}}'); + expect(capturedEvent.user?.id, fakeUser.id); + expect(capturedEvent.user?.email, fakeUser.email); }); }); @@ -510,7 +557,9 @@ void main() { final client = SentryClient(options); await client.captureEvent(fakeEvent); - final event = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final event = await eventFromEnvelope(capturedEnvelope); expect(event.tags!.containsKey('theme'), true); expect(event.extra!.containsKey('host'), true); @@ -551,7 +600,10 @@ void main() { final client = SentryClient(options); await client.captureEvent(fakeEvent); - final event = (options.transport as MockTransport).events.first; + final capturedEnvelope = + (options.transport as MockTransport).envelopes.first; + final event = await eventFromEnvelope(capturedEnvelope); + expect(event.tags!.containsKey('theme'), true); expect(event.extra!.containsKey('host'), true); expect(event.modules!.containsKey('core'), true); @@ -613,6 +665,16 @@ void main() { }); } +Future eventFromEnvelope(SentryEnvelope envelope) async { + final envelopeItemData = []; + await envelope.items.first + .envelopeItemStream() + .forEach(envelopeItemData.addAll); + final envelopeItem = utf8.decode(envelopeItemData); + final envelopeItemJson = jsonDecode(envelopeItem.split('\n').last); + return SentryEvent.fromJson(envelopeItemJson as Map); +} + SentryEvent? beforeSendCallbackDropEvent(SentryEvent event, {dynamic hint}) => null; From 6ae3cb91e45bffa542af9df5aa0e9495b72d0dc9 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 10:14:40 +0200 Subject: [PATCH 03/48] Fix SentryDevice serialization/deserialization --- dart/lib/src/protocol/sentry_device.dart | 6 +- dart/test/contexts_test.dart | 2 +- dart/test/protocol/sentry_device_test.dart | 87 ++++++++++++++++++++++ 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 dart/test/protocol/sentry_device_test.dart diff --git a/dart/lib/src/protocol/sentry_device.dart b/dart/lib/src/protocol/sentry_device.dart index 36bad0e280..7d8a304e14 100644 --- a/dart/lib/src/protocol/sentry_device.dart +++ b/dart/lib/src/protocol/sentry_device.dart @@ -45,7 +45,11 @@ class SentryDevice { modelId: data['model_id'], arch: data['arch'], batteryLevel: data['battery_level'], - orientation: data['orientation'], + orientation: data['orientation'] == 'portrait' + ? SentryOrientation.portrait + : data['orientation'] == 'landscape' + ? SentryOrientation.landscape + : null, manufacturer: data['manufacturer'], brand: data['brand'], screenResolution: data['screen_resolution'], diff --git a/dart/test/contexts_test.dart b/dart/test/contexts_test.dart index 5647f03144..feea85975c 100644 --- a/dart/test/contexts_test.dart +++ b/dart/test/contexts_test.dart @@ -73,7 +73,7 @@ void main() { 'model': 'testModel', 'model_id': 'testModelId', 'arch': 'testArch', - 'battery_level': 23, + 'battery_level': 23.0, 'orientation': 'landscape', 'manufacturer': 'testOEM', 'brand': 'testBrand', diff --git a/dart/test/protocol/sentry_device_test.dart b/dart/test/protocol/sentry_device_test.dart new file mode 100644 index 0000000000..acd140be3f --- /dev/null +++ b/dart/test/protocol/sentry_device_test.dart @@ -0,0 +1,87 @@ +import 'package:collection/collection.dart'; +import 'package:sentry/sentry.dart'; +import 'package:test/test.dart'; + +void main() { + + final testBootTime = DateTime.fromMicrosecondsSinceEpoch(0); + + final sentryDevice = SentryDevice( + name: 'testDevice', + family: 'testFamily', + model: 'testModel', + modelId: 'testModelId', + arch: 'testArch', + batteryLevel: 23.0, + orientation: SentryOrientation.landscape, + manufacturer: 'testOEM', + brand: 'testBrand', + screenResolution: '123x345', + screenDensity: 99.1, + screenDpi: 100, + online: false, + charging: true, + lowMemory: false, + simulator: true, + memorySize: 1234567, + freeMemory: 12345, + usableMemory: 9876, + storageSize: 1234567, + freeStorage: 1234567, + externalStorageSize: 98765, + externalFreeStorage: 98765, + bootTime: testBootTime, + timezone: 'Australia/Melbourne', + ); + + final sentryDeviceJson = { + 'name': 'testDevice', + 'family': 'testFamily', + 'model': 'testModel', + 'model_id': 'testModelId', + 'arch': 'testArch', + 'battery_level': 23.0, + 'orientation': 'landscape', + 'manufacturer': 'testOEM', + 'brand': 'testBrand', + 'screen_resolution': '123x345', + 'screen_density': 99.1, + 'screen_dpi': 100, + 'online': false, + 'charging': true, + 'low_memory': false, + 'simulator': true, + 'memory_size': 1234567, + 'free_memory': 12345, + 'usable_memory': 9876, + 'storage_size': 1234567, + 'free_storage': 1234567, + 'external_storage_size': 98765, + 'external_free_storage': 98765, + 'boot_time': testBootTime.toIso8601String(), + 'timezone': 'Australia/Melbourne', + }; + + test('SentryDevice toJson', () { + final json = sentryDevice.toJson(); + + expect( + MapEquality().equals(sentryDeviceJson, json), + true, + ); + }); + + test('SentryDevice fromJson', () { + final sentryDevice = SentryDevice.fromJson(sentryDeviceJson); + final json = sentryDevice.toJson(); + + expect( + MapEquality().equals(sentryDeviceJson, json), + true, + ); + }); +} + + + + From 801da50e2e71c3532474744b42c8dd21b4181186 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 10:23:18 +0200 Subject: [PATCH 04/48] add tests for SentryGpu --- dart/test/protocol/sentry_gpu_test.dart | 53 +++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 dart/test/protocol/sentry_gpu_test.dart diff --git a/dart/test/protocol/sentry_gpu_test.dart b/dart/test/protocol/sentry_gpu_test.dart new file mode 100644 index 0000000000..b64e3465df --- /dev/null +++ b/dart/test/protocol/sentry_gpu_test.dart @@ -0,0 +1,53 @@ +import 'package:collection/collection.dart'; +import 'package:sentry/sentry.dart'; +import 'package:test/test.dart'; + +void main() { + + final sentryGpu = SentryGpu( + name: 'fixture-name', + id: 1, + vendorId: 2, + vendorName: 'fixture-vendorName', + memorySize: 3, + apiType: 'fixture-apiType', + multiThreadedRendering: true, + version: '4', + npotSupport: 'fixture-npotSupport' + ); + + final sentryGpuJson = { + 'name': 'fixture-name', + 'id': 1, + 'vendor_id': 2, + 'vendor_name': 'fixture-vendorName', + 'memory_size': 3, + 'api_type': 'fixture-apiType', + 'multi_threaded_rendering': true, + 'version': '4', + 'npot_support': 'fixture-npotSupport' + }; + + test('toJson', () { + final json = sentryGpu.toJson(); + + expect( + MapEquality().equals(sentryGpuJson, json), + true, + ); + }); + + test('fromJson', () { + final sentryGpu = SentryGpu.fromJson(sentryGpuJson); + final json = sentryGpu.toJson(); + + expect( + MapEquality().equals(sentryGpuJson, json), + true, + ); + }); +} + + + + From 966018a800ee8edd6ee80b7ac846cdd83ee06909 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 10:29:40 +0200 Subject: [PATCH 05/48] add sentryapp test --- dart/test/protocol/sentry_app_test.dart | 51 +++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 dart/test/protocol/sentry_app_test.dart diff --git a/dart/test/protocol/sentry_app_test.dart b/dart/test/protocol/sentry_app_test.dart new file mode 100644 index 0000000000..7738fef712 --- /dev/null +++ b/dart/test/protocol/sentry_app_test.dart @@ -0,0 +1,51 @@ +import 'package:collection/collection.dart'; +import 'package:sentry/sentry.dart'; +import 'package:test/test.dart'; + +void main() { + + final testStartTime = DateTime.fromMicrosecondsSinceEpoch(0); + + final sentryApp = SentryApp( + name: 'fixture-name', + version: 'fixture-version', + identifier: 'fixture-identifier', + build: 'fixture-build', + buildType: 'fixture-buildType', + startTime: testStartTime, + deviceAppHash: 'fixture-deviceAppHash' + ); + + final sentryAppJson = { + 'app_name': 'fixture-name', + 'app_version': 'fixture-version', + 'app_identifier': 'fixture-identifier', + 'app_build': 'fixture-build', + 'build_type': 'fixture-buildType', + 'app_start_time': testStartTime.toIso8601String(), + 'device_app_hash': 'fixture-deviceAppHash' + }; + + test('toJson', () { + final json = sentryApp.toJson(); + + expect( + MapEquality().equals(sentryAppJson, json), + true, + ); + }); + + test('fromJson', () { + final sentryApp = SentryApp.fromJson(sentryAppJson); + final json = sentryApp.toJson(); + + expect( + MapEquality().equals(sentryAppJson, json), + true, + ); + }); +} + + + + From b5209151de4fe6d18524cad9be54ba5158f9a507 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 10:36:31 +0200 Subject: [PATCH 06/48] add sentry browser test --- dart/test/protocol/sentry_browser_test.dart | 36 +++++++++++++++++++ dart/test/protocol/sentry_device_test.dart | 36 +++++++++---------- dart/test/protocol/sentry_gpu_test.dart | 39 ++++++++++----------- 3 files changed, 70 insertions(+), 41 deletions(-) create mode 100644 dart/test/protocol/sentry_browser_test.dart diff --git a/dart/test/protocol/sentry_browser_test.dart b/dart/test/protocol/sentry_browser_test.dart new file mode 100644 index 0000000000..76a54ad8da --- /dev/null +++ b/dart/test/protocol/sentry_browser_test.dart @@ -0,0 +1,36 @@ +import 'package:collection/collection.dart'; +import 'package:sentry/sentry.dart'; +import 'package:test/test.dart'; + +void main() { + + final sentryBrowser = SentryBrowser( + name: 'fixture-name', + version: 'fixture-version', + ); + + final sentryBrowserJson = { + 'name': 'fixture-name', + 'version': 'fixture-version', + }; + + group('json', () { + test('toJson', () { + final json = sentryBrowser.toJson(); + + expect( + MapEquality().equals(sentryBrowserJson, json), + true, + ); + }); + test('fromJson', () { + final sentryBrowser = SentryBrowser.fromJson(sentryBrowserJson); + final json = sentryBrowser.toJson(); + + expect( + MapEquality().equals(sentryBrowserJson, json), + true, + ); + }); + }); +} diff --git a/dart/test/protocol/sentry_device_test.dart b/dart/test/protocol/sentry_device_test.dart index acd140be3f..927163ab09 100644 --- a/dart/test/protocol/sentry_device_test.dart +++ b/dart/test/protocol/sentry_device_test.dart @@ -3,7 +3,6 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - final testBootTime = DateTime.fromMicrosecondsSinceEpoch(0); final sentryDevice = SentryDevice( @@ -62,26 +61,23 @@ void main() { 'timezone': 'Australia/Melbourne', }; - test('SentryDevice toJson', () { - final json = sentryDevice.toJson(); - - expect( - MapEquality().equals(sentryDeviceJson, json), - true, - ); - }); + group('json', () { + test('toJson', () { + final json = sentryDevice.toJson(); - test('SentryDevice fromJson', () { - final sentryDevice = SentryDevice.fromJson(sentryDeviceJson); - final json = sentryDevice.toJson(); + expect( + MapEquality().equals(sentryDeviceJson, json), + true, + ); + }); + test('fromJson', () { + final sentryDevice = SentryDevice.fromJson(sentryDeviceJson); + final json = sentryDevice.toJson(); - expect( - MapEquality().equals(sentryDeviceJson, json), - true, - ); + expect( + MapEquality().equals(sentryDeviceJson, json), + true, + ); + }); }); } - - - - diff --git a/dart/test/protocol/sentry_gpu_test.dart b/dart/test/protocol/sentry_gpu_test.dart index b64e3465df..102c1b2771 100644 --- a/dart/test/protocol/sentry_gpu_test.dart +++ b/dart/test/protocol/sentry_gpu_test.dart @@ -28,26 +28,23 @@ void main() { 'npot_support': 'fixture-npotSupport' }; - test('toJson', () { - final json = sentryGpu.toJson(); - - expect( - MapEquality().equals(sentryGpuJson, json), - true, - ); - }); - - test('fromJson', () { - final sentryGpu = SentryGpu.fromJson(sentryGpuJson); - final json = sentryGpu.toJson(); - - expect( - MapEquality().equals(sentryGpuJson, json), - true, - ); + group('json', () { + test('toJson', () { + final json = sentryGpu.toJson(); + + expect( + MapEquality().equals(sentryGpuJson, json), + true, + ); + }); + test('fromJson', () { + final sentryGpu = SentryGpu.fromJson(sentryGpuJson); + final json = sentryGpu.toJson(); + + expect( + MapEquality().equals(sentryGpuJson, json), + true, + ); + }); }); } - - - - From f994501c2702f7ec0b534087cf7ed26db884d8e8 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 10:42:01 +0200 Subject: [PATCH 07/48] Add SentryOperatingSystem json tests --- .../sentry_operating_system_test.dart | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 dart/test/protocol/sentry_operating_system_test.dart diff --git a/dart/test/protocol/sentry_operating_system_test.dart b/dart/test/protocol/sentry_operating_system_test.dart new file mode 100644 index 0000000000..82c796d839 --- /dev/null +++ b/dart/test/protocol/sentry_operating_system_test.dart @@ -0,0 +1,44 @@ +import 'package:collection/collection.dart'; +import 'package:sentry/sentry.dart'; +import 'package:test/test.dart'; + +void main() { + + final sentryOperatingSystem = SentryOperatingSystem( + name: 'fixture-name', + version: 'fixture-version', + build: 'fixture-build', + kernelVersion: 'fixture-kernelVersion', + rooted: true, + rawDescription: 'fixture-rawDescription' + ); + + final sentryOperatingSystemJson = { + 'name': 'fixture-name', + 'version': 'fixture-version', + 'build': 'fixture-build', + 'kernel_version': 'fixture-kernelVersion', + 'rooted': true, + 'raw_description': 'fixture-rawDescription' + }; + + group('json', () { + test('toJson', () { + final json = sentryOperatingSystem.toJson(); + + expect( + MapEquality().equals(sentryOperatingSystemJson, json), + true, + ); + }); + test('fromJson', () { + final sentryOperatingSystem = SentryOperatingSystem.fromJson(sentryOperatingSystemJson); + final json = sentryOperatingSystem.toJson(); + + expect( + MapEquality().equals(sentryOperatingSystemJson, json), + true, + ); + }); + }); +} From cbb981300197772d72688f3ddf48b13713956239 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 11:25:47 +0200 Subject: [PATCH 08/48] Update sentry runtime test --- dart/test/protocol/sentry_runtime_test.dart | 83 ++++++++++++++------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/dart/test/protocol/sentry_runtime_test.dart b/dart/test/protocol/sentry_runtime_test.dart index 75878c6d2c..caa747b070 100644 --- a/dart/test/protocol/sentry_runtime_test.dart +++ b/dart/test/protocol/sentry_runtime_test.dart @@ -3,37 +3,66 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - final copy = data.copyWith(); + final sentryRuntime = SentryRuntime( + key: 'key', + name: 'name', + version: 'version', + rawDescription: 'rawDescription', + ); - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); + final sentryRuntimeJson = { + 'name': 'name', + 'version': 'version', + 'raw_description': 'rawDescription', + }; - test('copyWith takes new values', () { - final data = _generate(); + group('json', () { + test('toJson', () { + final json = sentryRuntime.toJson(); - final copy = data.copyWith( - key: 'key1', - name: 'name1', - version: 'version1', - rawDescription: 'rawDescription1', - ); + expect( + MapEquality().equals(sentryRuntimeJson, json), + true, + ); + }); + test('fromJson', () { + final sentryRuntime = SentryRuntime.fromJson(sentryRuntimeJson); + final json = sentryRuntime.toJson(); - expect('key1', copy.key); - expect('name1', copy.name); - expect('version1', copy.version); - expect('rawDescription1', copy.rawDescription); + expect( + MapEquality().equals(sentryRuntimeJson, json), + true, + ); + }); }); -} -SentryRuntime _generate() => SentryRuntime( - key: 'key', - name: 'name', - version: 'version', - rawDescription: 'rawDescription', - ); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryRuntime; + + final copy = data.copyWith(); + + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + + test('copyWith takes new values', () { + final data = sentryRuntime; + + final copy = data.copyWith( + key: 'key1', + name: 'name1', + version: 'version1', + rawDescription: 'rawDescription1', + ); + + expect('key1', copy.key); + expect('name1', copy.name); + expect('version1', copy.version); + expect('rawDescription1', copy.rawDescription); + }); + }); +} From 7e154d139ea50afc40e4fdbbbef481eb76824863 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 11:26:03 +0200 Subject: [PATCH 09/48] Add deserialize/serialize test to context test --- dart/test/contexts_test.dart | 89 ++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 40 deletions(-) diff --git a/dart/test/contexts_test.dart b/dart/test/contexts_test.dart index feea85975c..5bd97189d0 100644 --- a/dart/test/contexts_test.dart +++ b/dart/test/contexts_test.dart @@ -61,50 +61,59 @@ void main() { ..['theme'] = {'value': 'material'} ..['version'] = {'value': 9}; + final contextsJson = { + 'device': { + 'name': 'testDevice', + 'family': 'testFamily', + 'model': 'testModel', + 'model_id': 'testModelId', + 'arch': 'testArch', + 'battery_level': 23.0, + 'orientation': 'landscape', + 'manufacturer': 'testOEM', + 'brand': 'testBrand', + 'screen_resolution': '123x345', + 'screen_density': 99.1, + 'screen_dpi': 100, + 'online': false, + 'charging': true, + 'low_memory': false, + 'simulator': true, + 'memory_size': 1234567, + 'free_memory': 12345, + 'usable_memory': 9876, + 'storage_size': 1234567, + 'free_storage': 1234567, + 'external_storage_size': 98765, + 'external_free_storage': 98765, + 'boot_time': testBootTime.toIso8601String(), + 'timezone': 'Australia/Melbourne', + }, + 'os': { + 'name': 'testOS', + }, + 'app': {'app_version': '1.2.3'}, + 'browser': {'version': '12.3.4'}, + 'gpu': {'name': 'Radeon', 'version': '1'}, + 'testrt1': {'name': 'testRT1', 'type': 'runtime', 'version': '1.0'}, + 'testrt2': {'name': 'testRT2', 'type': 'runtime', 'version': '2.3.1'}, + 'theme': {'value': 'material'}, + 'version': {'value': 9}, + }; + test('serializes to JSON', () { final event = SentryEvent(contexts: contexts); + expect(event.toJson()['contexts'], contextsJson); + }); + + test('deserializes/serializes JSON', () { + final contexts = Contexts.fromJson(contextsJson); + final json = contexts.toJson(); + expect( - event.toJson()['contexts'], - { - 'device': { - 'name': 'testDevice', - 'family': 'testFamily', - 'model': 'testModel', - 'model_id': 'testModelId', - 'arch': 'testArch', - 'battery_level': 23.0, - 'orientation': 'landscape', - 'manufacturer': 'testOEM', - 'brand': 'testBrand', - 'screen_resolution': '123x345', - 'screen_density': 99.1, - 'screen_dpi': 100, - 'online': false, - 'charging': true, - 'low_memory': false, - 'simulator': true, - 'memory_size': 1234567, - 'free_memory': 12345, - 'usable_memory': 9876, - 'storage_size': 1234567, - 'free_storage': 1234567, - 'external_storage_size': 98765, - 'external_free_storage': 98765, - 'boot_time': testBootTime.toIso8601String(), - 'timezone': 'Australia/Melbourne', - }, - 'os': { - 'name': 'testOS', - }, - 'testrt1': {'name': 'testRT1', 'type': 'runtime', 'version': '1.0'}, - 'testrt2': {'name': 'testRT2', 'type': 'runtime', 'version': '2.3.1'}, - 'app': {'app_version': '1.2.3'}, - 'browser': {'version': '12.3.4'}, - 'gpu': {'name': 'Radeon', 'version': '1'}, - 'theme': {'value': 'material'}, - 'version': {'value': 9}, - }, + DeepCollectionEquality().equals(contextsJson, json), + true, ); }); From b60821b878d039c59afe5b681afbb9eb13c75c1d Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 11:34:10 +0200 Subject: [PATCH 10/48] Deserialize contexts in sentry event --- dart/lib/src/protocol/sentry_event.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index fabfe8ed16..302211181d 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -272,6 +272,8 @@ class SentryEvent { }); } + final contextsJson = json['contexts'] as Map?; + return SentryEvent( eventId: SentryId.fromId(['event_id'].toString()), // TODO: Hanled '-'? timestamp: DateTime.now(), // TODO: Parse timestamp @@ -300,7 +302,9 @@ class SentryEvent { level: levelName != null ? SentryLevel.fromName(levelName) : null, culprit: json['culprit']?.toString(), user: userJson != null ? SentryUser.fromJson(userJson) : null, - contexts: null, // TODO(denis) + contexts: contextsJson != null + ? Contexts.fromJson(contextsJson) + : null, request: null, // TODO(denis) debugMeta: null, // TODO(denis) ); From 0300ebdc1b30c797f6b39214a16bc78ca86f7556 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 11:43:22 +0200 Subject: [PATCH 11/48] add json tests to sentry_request --- dart/lib/src/protocol/sentry_event.dart | 5 +- dart/lib/src/protocol/sentry_request.dart | 13 ++++ dart/test/protocol/request_test.dart | 42 ----------- dart/test/protocol/sentry_request_test.dart | 78 +++++++++++++++++++++ 4 files changed, 95 insertions(+), 43 deletions(-) delete mode 100644 dart/test/protocol/request_test.dart create mode 100644 dart/test/protocol/sentry_request_test.dart diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 302211181d..43f0cfd257 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -273,6 +273,7 @@ class SentryEvent { } final contextsJson = json['contexts'] as Map?; + final requestJson = json['request'] as Map?; return SentryEvent( eventId: SentryId.fromId(['event_id'].toString()), // TODO: Hanled '-'? @@ -305,7 +306,9 @@ class SentryEvent { contexts: contextsJson != null ? Contexts.fromJson(contextsJson) : null, - request: null, // TODO(denis) + request: requestJson != null + ? SentryRequest.fromJson(requestJson) + : null, debugMeta: null, // TODO(denis) ); } diff --git a/dart/lib/src/protocol/sentry_request.dart b/dart/lib/src/protocol/sentry_request.dart index acaef3370e..2edc11b1b3 100644 --- a/dart/lib/src/protocol/sentry_request.dart +++ b/dart/lib/src/protocol/sentry_request.dart @@ -69,6 +69,19 @@ class SentryRequest { _env = env != null ? Map.from(env) : null, _other = other != null ? Map.from(other) : null; + factory SentryRequest.fromJson(Map json) { + return SentryRequest( + url: json['url'], + method: json['method'], + queryString: json['query_string'], + cookies: json['cookies'], + data: json['data'], + headers: json['headers'], + env: json['env'], + other: json['other'], + ); + } + Map toJson() { final json = {}; diff --git a/dart/test/protocol/request_test.dart b/dart/test/protocol/request_test.dart deleted file mode 100644 index ef5e68fa45..0000000000 --- a/dart/test/protocol/request_test.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:sentry/sentry.dart'; -import 'package:test/test.dart'; - -void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - - final copy = data.copyWith(); - - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); - - test('copyWith takes new values', () { - final data = _generate(); - - final copy = data.copyWith( - url: 'url1', - method: 'method1', - queryString: 'queryString1', - cookies: 'cookies1', - data: {'key1': 'value1'}, - ); - - expect('url1', copy.url); - expect('method1', copy.method); - expect('queryString1', copy.queryString); - expect('cookies1', copy.cookies); - expect({'key1': 'value1'}, copy.data); - }); -} - -SentryRequest _generate() => SentryRequest( - url: 'url', - method: 'method', - queryString: 'queryString', - cookies: 'cookies', - data: {'key': 'value'}, - ); diff --git a/dart/test/protocol/sentry_request_test.dart b/dart/test/protocol/sentry_request_test.dart new file mode 100644 index 0000000000..ae78f75fdb --- /dev/null +++ b/dart/test/protocol/sentry_request_test.dart @@ -0,0 +1,78 @@ +import 'package:collection/collection.dart'; +import 'package:sentry/sentry.dart'; +import 'package:test/test.dart'; + +void main() { + final sentryRequest = SentryRequest( + url: 'url', + method: 'method', + queryString: 'queryString', + cookies: 'cookies', + data: {'key': 'value'}, + headers: {'header_key': 'header_value'}, + env: {'env_key': 'env_value'}, + other: {'other_key': 'other_value'}, + ); + + final sentryRequestJson = { + 'url': 'url', + 'method': 'method', + 'query_string': 'queryString', + 'cookies': 'cookies', + 'data': {'key': 'value'}, + 'headers': {'header_key': 'header_value'}, + 'env': {'env_key': 'env_value'}, + 'other': {'other_key': 'other_value'}, + }; + + group('json', () { + test('toJson', () { + final json = sentryRequest.toJson(); + + expect( + DeepCollectionEquality().equals(sentryRequestJson, json), + true, + ); + }); + test('fromJson', () { + final sentryRequest = SentryRequest.fromJson(sentryRequestJson); + final json = sentryRequest.toJson(); + + expect( + DeepCollectionEquality().equals(sentryRequestJson, json), + true, + ); + }); + }); + + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryRequest; + + final copy = data.copyWith(); + + expect( + DeepCollectionEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + + test('copyWith takes new values', () { + final data = sentryRequest; + + final copy = data.copyWith( + url: 'url1', + method: 'method1', + queryString: 'queryString1', + cookies: 'cookies1', + data: {'key1': 'value1'}, + ); + + expect('url1', copy.url); + expect('method1', copy.method); + expect('queryString1', copy.queryString); + expect('cookies1', copy.cookies); + expect({'key1': 'value1'}, copy.data); + }); + }); +} From d9805a89ae8a917edb38dcbdad1d434a3b316207 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 12:38:29 +0200 Subject: [PATCH 12/48] Test sdkinfo json --- dart/lib/src/protocol/sdk_info.dart | 9 +++ dart/test/protocol/sdk_info_test.dart | 80 ++++++++++++++++++--------- 2 files changed, 63 insertions(+), 26 deletions(-) diff --git a/dart/lib/src/protocol/sdk_info.dart b/dart/lib/src/protocol/sdk_info.dart index a58ab63e73..7e3ce1fd73 100644 --- a/dart/lib/src/protocol/sdk_info.dart +++ b/dart/lib/src/protocol/sdk_info.dart @@ -15,6 +15,15 @@ class SdkInfo { this.versionPatchlevel, }); + factory SdkInfo.fromJson(Map json) { + return SdkInfo( + sdkName: json['sdk_name'], + versionMajor: json['version_major'], + versionMinor: json['version_minor'], + versionPatchlevel: json['version_patchlevel'], + ); + } + Map toJson() { final json = {}; if (sdkName != null) { diff --git a/dart/test/protocol/sdk_info_test.dart b/dart/test/protocol/sdk_info_test.dart index bee6f36ff8..50e3c3fdcd 100644 --- a/dart/test/protocol/sdk_info_test.dart +++ b/dart/test/protocol/sdk_info_test.dart @@ -3,37 +3,65 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); + final sdkInfo = SdkInfo( + sdkName: 'sdkName', + versionMajor: 1, + versionMinor: 2, + versionPatchlevel: 3, + ); - final copy = data.copyWith(); + final sdkInfoJson = { + 'sdk_name': 'sdkName', + 'version_major': 1, + 'version_minor': 2, + 'version_patchlevel': 3, + }; - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); + group('json', () { + test('toJson', () { + final json = sdkInfo.toJson(); + + expect( + MapEquality().equals(sdkInfoJson, json), + true, + ); + }); + test('fromJson', () { + final sdkInfo = SdkInfo.fromJson(sdkInfoJson); + final json = sdkInfo.toJson(); + + expect( + MapEquality().equals(sdkInfoJson, json), + true, + ); + }); }); - test('copyWith takes new values', () { - final data = _generate(); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sdkInfo; + + final copy = data.copyWith(); - final copy = data.copyWith( - sdkName: 'sdkName1', - versionMajor: 11, - versionMinor: 22, - versionPatchlevel: 33, - ); + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + test('copyWith takes new values', () { + final data = sdkInfo; - expect('sdkName1', copy.sdkName); - expect(11, copy.versionMajor); - expect(22, copy.versionMinor); - expect(33, copy.versionPatchlevel); + final copy = data.copyWith( + sdkName: 'sdkName1', + versionMajor: 11, + versionMinor: 22, + versionPatchlevel: 33, + ); + + expect('sdkName1', copy.sdkName); + expect(11, copy.versionMajor); + expect(22, copy.versionMinor); + expect(33, copy.versionPatchlevel); + }); }); } - -SdkInfo _generate() => SdkInfo( - sdkName: 'sdkName', - versionMajor: 1, - versionMinor: 2, - versionPatchlevel: 3, - ); From 178ea70ee8f47880a0bc339a367ca33246a92880 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 13:01:20 +0200 Subject: [PATCH 13/48] add DebugMeta decoding --- dart/lib/src/protocol/debug_image.dart | 14 +++ dart/lib/src/protocol/debug_meta.dart | 13 +++ dart/test/protocol/debug_image_test.dart | 120 +++++++++++++++-------- dart/test/protocol/debug_meta_test.dart | 95 +++++++++++------- 4 files changed, 166 insertions(+), 76 deletions(-) diff --git a/dart/lib/src/protocol/debug_image.dart b/dart/lib/src/protocol/debug_image.dart index 4fd3eb1972..3017cb0c4c 100644 --- a/dart/lib/src/protocol/debug_image.dart +++ b/dart/lib/src/protocol/debug_image.dart @@ -50,6 +50,20 @@ class DebugImage { this.codeId, }); + factory DebugImage.fromJson(Map json) { + return DebugImage( + type: json['type'], + imageAddr: json['image_addr'], + debugId: json['debug_id'], + debugFile: json['debug_file'], + imageSize: json['image_size'], + uuid: json['uuid'], + codeFile: json['code_file'], + arch: json['arch'], + codeId: json['code_id'], + ); + } + Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/debug_meta.dart b/dart/lib/src/protocol/debug_meta.dart index 1b6aebd993..9fef91508a 100644 --- a/dart/lib/src/protocol/debug_meta.dart +++ b/dart/lib/src/protocol/debug_meta.dart @@ -18,6 +18,19 @@ class DebugMeta { DebugMeta({this.sdk, List? images}) : _images = images; + factory DebugMeta.fromJson(Map json) { + final sdkInfoJson = json['sdk_info']; + final debugImagesJson = json['images'] as List?; + return DebugMeta( + sdk: sdkInfoJson != null ? SdkInfo.fromJson(sdkInfoJson) : null, + images: debugImagesJson != null + ? debugImagesJson + .map((debugImageJson) => DebugImage.fromJson( + debugImageJson as Map) + ).toList() + : null); + } + Map toJson() { final json = {}; diff --git a/dart/test/protocol/debug_image_test.dart b/dart/test/protocol/debug_image_test.dart index a22b947b8d..427eb19b8a 100644 --- a/dart/test/protocol/debug_image_test.dart +++ b/dart/test/protocol/debug_image_test.dart @@ -3,52 +3,86 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); + final debugImage = DebugImage( + type: 'type', + imageAddr: 'imageAddr', + debugId: 'debugId', + debugFile: 'debugFile', + imageSize: 1, + uuid: 'uuid', + codeFile: 'codeFile', + arch: 'arch', + codeId: 'codeId', + ); - final copy = data.copyWith(); + final debugImageJson = { + 'uuid': 'uuid', + 'type': 'type', + 'debug_id': 'debugId', + 'debug_file': 'debugFile', + 'code_file': 'codeFile', + 'image_addr': 'imageAddr', + 'image_size': 1, + 'arch': 'arch', + 'code_id': 'codeId', + }; - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); + group('json', () { + test('toJson', () { + final json = debugImage.toJson(); + + expect( + MapEquality().equals(debugImageJson, json), + true, + ); + }); + test('fromJson', () { + final debugImage = DebugImage.fromJson(debugImageJson); + final json = debugImage.toJson(); + + expect( + MapEquality().equals(debugImageJson, json), + true, + ); + }); }); - test('copyWith takes new values', () { - final data = _generate(); - - final copy = data.copyWith( - type: 'type1', - imageAddr: 'imageAddr1', - debugId: 'debugId1', - debugFile: 'debugFile1', - imageSize: 2, - uuid: 'uuid1', - codeFile: 'codeFile1', - arch: 'arch1', - codeId: 'codeId1', - ); - - expect('type1', copy.type); - expect('imageAddr1', copy.imageAddr); - expect('debugId1', copy.debugId); - expect('debugFile1', copy.debugFile); - expect(2, copy.imageSize); - expect('uuid1', copy.uuid); - expect('codeFile1', copy.codeFile); - expect('arch1', copy.arch); - expect('codeId1', copy.codeId); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = debugImage; + + final copy = data.copyWith(); + + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + + test('copyWith takes new values', () { + final data = debugImage; + + final copy = data.copyWith( + type: 'type1', + imageAddr: 'imageAddr1', + debugId: 'debugId1', + debugFile: 'debugFile1', + imageSize: 2, + uuid: 'uuid1', + codeFile: 'codeFile1', + arch: 'arch1', + codeId: 'codeId1', + ); + + expect('type1', copy.type); + expect('imageAddr1', copy.imageAddr); + expect('debugId1', copy.debugId); + expect('debugFile1', copy.debugFile); + expect(2, copy.imageSize); + expect('uuid1', copy.uuid); + expect('codeFile1', copy.codeFile); + expect('arch1', copy.arch); + expect('codeId1', copy.codeId); + }); }); } - -DebugImage _generate() => DebugImage( - type: 'type', - imageAddr: 'imageAddr', - debugId: 'debugId', - debugFile: 'debugFile', - imageSize: 1, - uuid: 'uuid', - codeFile: 'codeFile', - arch: 'arch', - codeId: 'codeId', - ); diff --git a/dart/test/protocol/debug_meta_test.dart b/dart/test/protocol/debug_meta_test.dart index b611bc9828..64dd3c5eb1 100644 --- a/dart/test/protocol/debug_meta_test.dart +++ b/dart/test/protocol/debug_meta_test.dart @@ -3,42 +3,71 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); + final debugMeta = DebugMeta( + sdk: SdkInfo( + sdkName: 'sdkName', + ), + images: [DebugImage(type: 'macho', uuid: 'uuid')], + ); - final copy = data.copyWith(); + final debugMetaJson = { + 'sdk_info': {'sdk_name': 'sdkName'}, + 'images': [{ + 'uuid': 'uuid', + 'type': 'macho' + }] + }; - // MapEquality fails for some reason, it probably check the instances equality too - expect(data.toJson(), copy.toJson()); + group('json', () { + test('toJson', () { + final json = debugMeta.toJson(); + + expect( + DeepCollectionEquality().equals(debugMetaJson, json), + true, + ); + }); + test('fromJson', () { + final debugMeta = DebugMeta.fromJson(debugMetaJson); + final json = debugMeta.toJson(); + + expect( + DeepCollectionEquality().equals(debugMetaJson, json), + true, + ); + }); }); - test('copyWith takes new values', () { - final data = _generate(); - - final newSdkInfo = SdkInfo( - sdkName: 'sdkName1', - ); - final newImageList = [DebugImage(type: 'macho', uuid: 'uuid1')]; - - final copy = data.copyWith( - sdk: newSdkInfo, - images: newImageList, - ); - - expect( - ListEquality().equals(newImageList, copy.images), - true, - ); - expect( - MapEquality().equals(newSdkInfo.toJson(), copy.sdk!.toJson()), - true, - ); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = debugMeta; + + final copy = data.copyWith(); + + // MapEquality fails for some reason, it probably check the instances equality too + expect(data.toJson(), copy.toJson()); + }); + test('copyWith takes new values', () { + final data = debugMeta; + + final newSdkInfo = SdkInfo( + sdkName: 'sdkName1', + ); + final newImageList = [DebugImage(type: 'macho', uuid: 'uuid1')]; + + final copy = data.copyWith( + sdk: newSdkInfo, + images: newImageList, + ); + + expect( + ListEquality().equals(newImageList, copy.images), + true, + ); + expect( + MapEquality().equals(newSdkInfo.toJson(), copy.sdk!.toJson()), + true, + ); + }); }); } - -DebugMeta _generate() => DebugMeta( - sdk: SdkInfo( - sdkName: 'sdkName', - ), - images: [DebugImage(type: 'macho', uuid: 'uuid')], - ); From 2a614d1b5c23626f10283d6e05fad51eac1448ad Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 13:27:13 +0200 Subject: [PATCH 14/48] test sdk version and sentry package --- dart/lib/src/protocol/sentry_event.dart | 61 +++++------- dart/test/protocol/sdk_version_test.dart | 100 +++++++++++++------- dart/test/protocol/sentry_package_test.dart | 67 +++++++++---- 3 files changed, 139 insertions(+), 89 deletions(-) diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 43f0cfd257..5fb4facc8a 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -232,27 +232,20 @@ class SentryEvent { return Breadcrumb.fromJson(e); }).toList(); - final sdkJson = json['sdk'] as Map?; - final messageJson = json['message'] as Map?; - - final stackTraceJson = json['threads'] as Map?; - final stackTraceValuesJson = stackTraceJson?['values'] as List?; + final stackTraceValuesJson = json['threads']?['values']; Map? stackTraceValuesStacktraceJson; if (stackTraceValuesJson?.isNotEmpty == true) { + stackTraceValuesStacktraceJson = {}; stackTraceValuesStacktraceJson = - stackTraceValuesJson?.first['stacktrace'] as Map?; + stackTraceValuesJson?.first['stacktrace']; } - final exceptionJson = json['exception'] as Map?; - final exceptionValuesJson = exceptionJson?['values'] as List?; - final exceptionValuesItemJson = - exceptionValuesJson?.first as Map?; - - final levelName = json['level']?.toString(); - - final userJson = json['user'] as Map?; - - final fingerprintJson = json['fingerprint'] as List?; + final exceptionValuesJson = json['exception']?['values']; + Map? exceptionValuesItemJson; + if (exceptionValuesJson?.isNotEmpty == true) { + exceptionValuesItemJson = {}; + exceptionValuesItemJson = exceptionValuesJson?.first; + } final modulesJson = json['modules'] as Map?; Map? modules; @@ -272,27 +265,24 @@ class SentryEvent { }); } - final contextsJson = json['contexts'] as Map?; - final requestJson = json['request'] as Map?; - return SentryEvent( - eventId: SentryId.fromId(['event_id'].toString()), // TODO: Hanled '-'? + eventId: SentryId.fromId(json['event_id']), // TODO: Hanled '-'? timestamp: DateTime.now(), // TODO: Parse timestamp modules: modules, tags: tags, - extra: json['extra'] as Map?, - fingerprint: fingerprintJson != null - ? fingerprintJson.map((e) => e as String).toList() - : null, + extra: json['extra'], + fingerprint: json['fingerprint']?.map((e) => e as String).toList(), breadcrumbs: breadcrumbs, - sdk: sdkJson != null ? SdkVersion.fromJson(sdkJson) : null, + sdk: json['sdk'] != null ? SdkVersion.fromJson(json['sdk']) : null, platform: json['platform']?.toString(), logger: json['logger']?.toString(), serverName: json['server_name']?.toString(), release: json['release']?.toString(), dist: json['dist']?.toString(), environment: json['environment']?.toString(), - message: messageJson != null ? SentryMessage.fromJson(messageJson) : null, + message: json['message'] != null + ? SentryMessage.fromJson(json['message']) + : null, transaction: json['transaction']?.toString(), stackTrace: stackTraceValuesStacktraceJson != null ? SentryStackTrace.fromJson(stackTraceValuesStacktraceJson) @@ -300,16 +290,17 @@ class SentryEvent { exception: exceptionValuesItemJson != null ? SentryException.fromJson(exceptionValuesItemJson) : null, - level: levelName != null ? SentryLevel.fromName(levelName) : null, + level: json['level'] != null ? SentryLevel.fromName(json['level']) : null, culprit: json['culprit']?.toString(), - user: userJson != null ? SentryUser.fromJson(userJson) : null, - contexts: contextsJson != null - ? Contexts.fromJson(contextsJson) - : null, - request: requestJson != null - ? SentryRequest.fromJson(requestJson) - : null, - debugMeta: null, // TODO(denis) + user: json['user'] != null ? SentryUser.fromJson(json['user']) : null, + contexts: + json['contexts'] != null ? Contexts.fromJson(json['contexts']) : null, + request: json['request'] != null + ? SentryRequest.fromJson(json['request']) + : null, + debugMeta: json['debug_meta'] != null + ? DebugMeta.fromJson(json['debug_meta']) + : null, ); } diff --git a/dart/test/protocol/sdk_version_test.dart b/dart/test/protocol/sdk_version_test.dart index 35d6afcdfc..a9189ee3e9 100644 --- a/dart/test/protocol/sdk_version_test.dart +++ b/dart/test/protocol/sdk_version_test.dart @@ -3,43 +3,75 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); + final sdkVersion = SdkVersion( + name: 'name', + version: 'version', + integrations: ['test'], + packages: [SentryPackage('name', 'version')], + ); - final copy = data.copyWith(); + final sdkVersionJson = { + 'name': 'name', + 'version': 'version', + 'integrations': ['test'], + 'packages': [{ + 'name': 'name', + 'version': 'version', + }], + }; - expect(data.toJson(), copy.toJson()); + group('json', () { + test('toJson', () { + final json = sdkVersion.toJson(); + + expect( + DeepCollectionEquality().equals(sdkVersionJson, json), + true, + ); + }); + test('fromJson', () { + final sdkVersion = SdkVersion.fromJson(sdkVersionJson); + final json = sdkVersion.toJson(); + + expect( + DeepCollectionEquality().equals(sdkVersionJson, json), + true, + ); + }); }); - test('copyWith takes new values', () { - final data = _generate(); - - final packages = [SentryPackage('name1', 'version1')]; - final integrations = ['test1']; - - final copy = data.copyWith( - name: 'name1', - version: 'version1', - integrations: integrations, - packages: packages, - ); - - expect( - ListEquality().equals(integrations, copy.integrations), - true, - ); - expect( - ListEquality().equals(packages, copy.packages), - true, - ); - expect('name1', copy.name); - expect('version1', copy.version); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sdkVersion; + + final copy = data.copyWith(); + + expect(data.toJson(), copy.toJson()); + }); + + test('copyWith takes new values', () { + final data = sdkVersion; + + final packages = [SentryPackage('name1', 'version1')]; + final integrations = ['test1']; + + final copy = data.copyWith( + name: 'name1', + version: 'version1', + integrations: integrations, + packages: packages, + ); + + expect( + ListEquality().equals(integrations, copy.integrations), + true, + ); + expect( + ListEquality().equals(packages, copy.packages), + true, + ); + expect('name1', copy.name); + expect('version1', copy.version); + }); }); } - -SdkVersion _generate() => SdkVersion( - name: 'name', - version: 'version', - integrations: ['test'], - packages: [SentryPackage('name', 'version')], - ); diff --git a/dart/test/protocol/sentry_package_test.dart b/dart/test/protocol/sentry_package_test.dart index 35e1ffd75e..9e7ed0ccd8 100644 --- a/dart/test/protocol/sentry_package_test.dart +++ b/dart/test/protocol/sentry_package_test.dart @@ -3,31 +3,58 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - final copy = data.copyWith(); + final sentryPackage = SentryPackage( + 'name', + 'version', + ); - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); + final sentryPackageJson = { + 'name': 'name', + 'version': 'version', + }; + + group('json', () { + test('toJson', () { + final json = sentryPackage.toJson(); + + expect( + MapEquality().equals(sentryPackageJson, json), + true, + ); + }); + test('fromJson', () { + final sentryPackage = SdkVersion.fromJson(sentryPackageJson); + final json = sentryPackage.toJson(); + + expect( + MapEquality().equals(sentryPackageJson, json), + true, + ); + }); }); - test('copyWith takes new values', () { - final data = _generate(); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryPackage; - final copy = data.copyWith( - name: 'name1', - version: 'version1', - ); + final copy = data.copyWith(); - expect('name1', copy.name); - expect('version1', copy.version); + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + test('copyWith takes new values', () { + final data = sentryPackage; + + final copy = data.copyWith( + name: 'name1', + version: 'version1', + ); + + expect('name1', copy.name); + expect('version1', copy.version); + }); }); } - -SentryPackage _generate() => SentryPackage( - 'name', - 'version', - ); From 217f5fff8f36de4ae6a8f555f7bc959faa689da3 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 13:31:58 +0200 Subject: [PATCH 15/48] Add json tests for sentry_message --- dart/test/protocol/message_test.dart | 36 ------------ dart/test/protocol/sentry_message_test.dart | 64 +++++++++++++++++++++ 2 files changed, 64 insertions(+), 36 deletions(-) delete mode 100644 dart/test/protocol/message_test.dart create mode 100644 dart/test/protocol/sentry_message_test.dart diff --git a/dart/test/protocol/message_test.dart b/dart/test/protocol/message_test.dart deleted file mode 100644 index 7705b82673..0000000000 --- a/dart/test/protocol/message_test.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:sentry/sentry.dart'; -import 'package:test/test.dart'; - -void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - - final copy = data.copyWith(); - - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); - - test('copyWith takes new values', () { - final data = _generate(); - - final copy = data.copyWith( - formatted: 'message 21', - template: 'message 2 %d', - params: ['2'], - ); - - expect('message 21', copy.formatted); - expect('message 2 %d', copy.template); - expect(['2'], copy.params); - }); -} - -SentryMessage _generate() => SentryMessage( - 'message 1', - template: 'message %d', - params: ['1'], - ); diff --git a/dart/test/protocol/sentry_message_test.dart b/dart/test/protocol/sentry_message_test.dart new file mode 100644 index 0000000000..7112642ed2 --- /dev/null +++ b/dart/test/protocol/sentry_message_test.dart @@ -0,0 +1,64 @@ +import 'package:collection/collection.dart'; +import 'package:sentry/sentry.dart'; +import 'package:test/test.dart'; + +void main() { + final sentryMessage = SentryMessage( + 'message 1', + template: 'message %d', + params: ['1'], + ); + + final sentryMessageJson = { + 'formatted': 'message 1', + 'message': 'message %d', + 'params': ['1'], + }; + + group('json', () { + test('toJson', () { + final json = sentryMessage.toJson(); + + expect( + DeepCollectionEquality().equals(sentryMessageJson, json), + true, + ); + }); + test('fromJson', () { + final sentryMessage = SentryMessage.fromJson(sentryMessageJson); + final json = sentryMessage.toJson(); + + expect( + DeepCollectionEquality().equals(sentryMessageJson, json), + true, + ); + }); + }); + + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryMessage; + + final copy = data.copyWith(); + + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + + test('copyWith takes new values', () { + final data = sentryMessage; + + final copy = data.copyWith( + formatted: 'message 21', + template: 'message 2 %d', + params: ['2'], + ); + + expect('message 21', copy.formatted); + expect('message 2 %d', copy.template); + expect(['2'], copy.params); + }); + }); +} From 7811216d34a8427ed8077df41d2ea6e07b635738 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 13:45:04 +0200 Subject: [PATCH 16/48] test SentryStackFrame, remove duplicate key in toJson --- dart/lib/src/protocol/sentry_stack_frame.dart | 42 ++--- .../protocol/sentry_stack_frame_test.dart | 178 +++++++++++------- 2 files changed, 130 insertions(+), 90 deletions(-) diff --git a/dart/lib/src/protocol/sentry_stack_frame.dart b/dart/lib/src/protocol/sentry_stack_frame.dart index 9a5fd0279b..0c761cd60a 100644 --- a/dart/lib/src/protocol/sentry_stack_frame.dart +++ b/dart/lib/src/protocol/sentry_stack_frame.dart @@ -110,25 +110,25 @@ class SentryStackFrame { factory SentryStackFrame.fromJson(Map json) { return SentryStackFrame( - absPath: json['abs_path']?.toString(), - fileName: json['filename']?.toString(), - function: json['function']?.toString(), - module: json['module']?.toString(), - lineNo: json['lineno'] as int?, - colNo: json['colno'] as int?, - contextLine: json['context_line']?.toString(), - inApp: json['in_app'] as bool?, - package: json['package']?.toString(), - native: json['native'] as bool?, - platform: json['platform']?.toString(), - imageAddr: json['image_addr']?.toString(), - symbolAddr: json['symbol_addr']?.toString(), - instructionAddr: json['instruction_addr']?.toString(), - rawFunction: json['raw_function']?.toString(), - framesOmitted: json['raw_function'] as List?, - preContext: json['pre_context'] as List?, - postContext: json['post_context'] as List?, - vars: json['vars'] as Map?, + absPath: json['abs_path'], + fileName: json['filename'], + function: json['function'], + module: json['module'], + lineNo: json['lineno'], + colNo: json['colno'], + contextLine: json['context_line'], + inApp: json['in_app'], + package: json['package'], + native: json['native'], + platform: json['platform'], + imageAddr: json['image_addr'], + symbolAddr: json['symbol_addr'], + instructionAddr: json['instruction_addr'], + rawFunction: json['raw_function'], + framesOmitted: json['frames_omitted'], + preContext: json['pre_context'], + postContext: json['post_context'], + vars: json['vars'], ); } @@ -187,10 +187,6 @@ class SentryStackFrame { json['in_app'] = inApp; } - if (package != null) { - json['package'] = package; - } - if (native != null) { json['native'] = native; } diff --git a/dart/test/protocol/sentry_stack_frame_test.dart b/dart/test/protocol/sentry_stack_frame_test.dart index 3690e77f53..69b5ad30fa 100644 --- a/dart/test/protocol/sentry_stack_frame_test.dart +++ b/dart/test/protocol/sentry_stack_frame_test.dart @@ -1,79 +1,123 @@ +import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); + final sentryStackFrame = SentryStackFrame( + absPath: 'absPath', + fileName: 'fileName', + function: 'function', + module: 'module', + lineNo: 1, + colNo: 2, + contextLine: 'contextLine', + inApp: true, + package: 'package', + native: false, + platform: 'platform', + imageAddr: 'imageAddr', + symbolAddr: 'symbolAddr', + instructionAddr: 'instructionAddr', + rawFunction: 'rawFunction', + framesOmitted: [1], + preContext: ['a'], + postContext: ['b'], + vars: {'key': 'value'}, + ); - final copy = data.copyWith(); + final sentryStackFrameJson = { + 'pre_context': ['a'], + 'post_context': ['b'], + 'vars': {'key': 'value'}, + 'frames_omitted': [1], + 'filename': 'fileName', + 'package': 'package', + 'function': 'function', + 'module': 'module', + 'lineno': 1, + 'colno': 2, + 'abs_path': 'absPath', + 'context_line': 'contextLine', + 'in_app': true, + 'native': false, + 'platform': 'platform', + 'image_addr': 'imageAddr', + 'symbol_addr': 'symbolAddr', + 'instruction_addr': 'instructionAddr', + 'raw_function': 'rawFunction', + }; - expect(data.toJson(), copy.toJson()); + group('json', () { + test('toJson', () { + final json = sentryStackFrame.toJson(); + + expect( + DeepCollectionEquality().equals(sentryStackFrameJson, json), + true, + ); + }); + test('fromJson', () { + final sentryStackFrame = SentryStackFrame.fromJson(sentryStackFrameJson); + final json = sentryStackFrame.toJson(); + + expect( + DeepCollectionEquality().equals(sentryStackFrameJson, json), + true, + ); + }); }); - test('copyWith takes new values', () { - final data = _generate(); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryStackFrame; + + final copy = data.copyWith(); - final copy = data.copyWith( - absPath: 'absPath1', - fileName: 'fileName1', - function: 'function1', - module: 'module1', - lineNo: 11, - colNo: 22, - contextLine: 'contextLine1', - inApp: false, - package: 'package1', - native: true, - platform: 'platform1', - imageAddr: 'imageAddr1', - symbolAddr: 'symbolAddr1', - instructionAddr: 'instructionAddr1', - rawFunction: 'rawFunction1', - framesOmitted: [11], - preContext: ['ab'], - postContext: ['bb'], - vars: {'key1': 'value1'}, - ); + expect(data.toJson(), copy.toJson()); + }); + test('copyWith takes new values', () { + final data = sentryStackFrame; - expect('absPath1', copy.absPath); - expect('fileName1', copy.fileName); - expect('function1', copy.function); - expect('module1', copy.module); - expect(11, copy.lineNo); - expect(22, copy.colNo); - expect(false, copy.inApp); - expect('package1', copy.package); - expect(true, copy.native); - expect('platform1', copy.platform); - expect('imageAddr1', copy.imageAddr); - expect('symbolAddr1', copy.symbolAddr); - expect('instructionAddr1', copy.instructionAddr); - expect('rawFunction1', copy.rawFunction); - expect([11], copy.framesOmitted); - expect(['ab'], copy.preContext); - expect(['bb'], copy.postContext); - expect({'key1': 'value1'}, copy.vars); + final copy = data.copyWith( + absPath: 'absPath1', + fileName: 'fileName1', + function: 'function1', + module: 'module1', + lineNo: 11, + colNo: 22, + contextLine: 'contextLine1', + inApp: false, + package: 'package1', + native: true, + platform: 'platform1', + imageAddr: 'imageAddr1', + symbolAddr: 'symbolAddr1', + instructionAddr: 'instructionAddr1', + rawFunction: 'rawFunction1', + framesOmitted: [11], + preContext: ['ab'], + postContext: ['bb'], + vars: {'key1': 'value1'}, + ); + + expect('absPath1', copy.absPath); + expect('fileName1', copy.fileName); + expect('function1', copy.function); + expect('module1', copy.module); + expect(11, copy.lineNo); + expect(22, copy.colNo); + expect(false, copy.inApp); + expect('package1', copy.package); + expect(true, copy.native); + expect('platform1', copy.platform); + expect('imageAddr1', copy.imageAddr); + expect('symbolAddr1', copy.symbolAddr); + expect('instructionAddr1', copy.instructionAddr); + expect('rawFunction1', copy.rawFunction); + expect([11], copy.framesOmitted); + expect(['ab'], copy.preContext); + expect(['bb'], copy.postContext); + expect({'key1': 'value1'}, copy.vars); + }); }); } - -SentryStackFrame _generate() => SentryStackFrame( - absPath: 'absPath', - fileName: 'fileName', - function: 'function', - module: 'module', - lineNo: 1, - colNo: 2, - contextLine: 'contextLine', - inApp: true, - package: 'package', - native: false, - platform: 'platform', - imageAddr: 'imageAddr', - symbolAddr: 'symbolAddr', - instructionAddr: 'instructionAddr', - rawFunction: 'rawFunction', - framesOmitted: [1], - preContext: ['a'], - postContext: ['b'], - vars: {'key': 'value'}, - ); From ace8e05e4dbdad9a1e8b1642ded7c44af4cee337 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 13:47:29 +0200 Subject: [PATCH 17/48] Add SentryStackTrace josn test --- .../protocol/sentry_stack_trace_test.dart | 85 +++++++++++++------ 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/dart/test/protocol/sentry_stack_trace_test.dart b/dart/test/protocol/sentry_stack_trace_test.dart index 8f74f3c59e..ce3f4817d6 100644 --- a/dart/test/protocol/sentry_stack_trace_test.dart +++ b/dart/test/protocol/sentry_stack_trace_test.dart @@ -3,37 +3,66 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); + final sentryStackTrace = SentryStackTrace( + frames: [SentryStackFrame(absPath: 'abs')], + registers: {'key': 'value'}, + ); - final copy = data.copyWith(); + final sentryStackTraceJson = { + 'frames': [ + {'abs_path': 'abs'} + ], + 'registers': {'key': 'value'}, + }; - expect(data.toJson(), copy.toJson()); + group('json', () { + test('toJson', () { + final json = sentryStackTrace.toJson(); + + expect( + DeepCollectionEquality().equals(sentryStackTraceJson, json), + true, + ); + }); + test('fromJson', () { + final sentryStackTrace = SentryStackTrace.fromJson(sentryStackTraceJson); + final json = sentryStackTrace.toJson(); + + expect( + DeepCollectionEquality().equals(sentryStackTraceJson, json), + true, + ); + }); }); - test('copyWith takes new values', () { - final data = _generate(); - - final frames = [SentryStackFrame(absPath: 'abs1')]; - final registers = {'key1': 'value1'}; - - final copy = data.copyWith( - frames: frames, - registers: registers, - ); - - expect( - ListEquality().equals(frames, copy.frames), - true, - ); - expect( - MapEquality().equals(registers, copy.registers), - true, - ); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryStackTrace; + + final copy = data.copyWith(); + + expect(data.toJson(), copy.toJson()); + }); + + test('copyWith takes new values', () { + final data = sentryStackTrace; + + final frames = [SentryStackFrame(absPath: 'abs1')]; + final registers = {'key1': 'value1'}; + + final copy = data.copyWith( + frames: frames, + registers: registers, + ); + + expect( + ListEquality().equals(frames, copy.frames), + true, + ); + expect( + MapEquality().equals(registers, copy.registers), + true, + ); + }); }); } - -SentryStackTrace _generate() => SentryStackTrace( - frames: [SentryStackFrame(absPath: 'abs')], - registers: {'key': 'value'}, - ); From 3db2994d04814f86160d3e8208af5e973aeb73c7 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 14:01:14 +0200 Subject: [PATCH 18/48] Merge test files and add todos for remaining json tests --- dart/test/protocol/app_test.dart | 50 --------- dart/test/protocol/breadcrumb_test.dart | 2 + dart/test/protocol/browser_test.dart | 33 ------ dart/test/protocol/contexts_test.dart | 2 + dart/test/protocol/device_test.dart | 104 ------------------ dart/test/protocol/gpu_test.dart | 54 --------- dart/test/protocol/mechanism_test.dart | 2 + dart/test/protocol/operating_system_test.dart | 42 ------- dart/test/protocol/sentry_app_test.dart | 80 ++++++++++---- dart/test/protocol/sentry_browser_test.dart | 26 ++++- dart/test/protocol/sentry_device_test.dart | 73 ++++++++++++ dart/test/protocol/sentry_exception_test.dart | 2 + dart/test/protocol/sentry_gpu_test.dart | 58 ++++++++-- .../sentry_operating_system_test.dart | 48 ++++++-- .../{user_test.dart => sentry_user_test.dart} | 2 + 15 files changed, 250 insertions(+), 328 deletions(-) delete mode 100644 dart/test/protocol/app_test.dart delete mode 100644 dart/test/protocol/browser_test.dart delete mode 100644 dart/test/protocol/device_test.dart delete mode 100644 dart/test/protocol/gpu_test.dart delete mode 100644 dart/test/protocol/operating_system_test.dart rename dart/test/protocol/{user_test.dart => sentry_user_test.dart} (98%) diff --git a/dart/test/protocol/app_test.dart b/dart/test/protocol/app_test.dart deleted file mode 100644 index fe2abb0957..0000000000 --- a/dart/test/protocol/app_test.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:sentry/sentry.dart'; -import 'package:test/test.dart'; - -void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - - final copy = data.copyWith(); - - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); - - test('copyWith takes new values', () { - final data = _generate(); - - final startTime = DateTime.now(); - - final copy = data.copyWith( - name: 'name1', - version: 'version1', - identifier: 'identifier1', - build: 'build1', - buildType: 'buildType1', - startTime: startTime, - deviceAppHash: 'hash1', - ); - - expect('name1', copy.name); - expect('version1', copy.version); - expect('identifier1', copy.identifier); - expect('build1', copy.build); - expect('buildType1', copy.buildType); - expect(startTime, copy.startTime); - expect('hash1', copy.deviceAppHash); - }); -} - -SentryApp _generate({DateTime? startTime}) => SentryApp( - name: 'name', - version: 'version', - identifier: 'identifier', - build: 'build', - buildType: 'buildType', - startTime: startTime ?? DateTime.now(), - deviceAppHash: 'hash', - ); diff --git a/dart/test/protocol/breadcrumb_test.dart b/dart/test/protocol/breadcrumb_test.dart index 2c0f6a97a7..f85931c4ab 100644 --- a/dart/test/protocol/breadcrumb_test.dart +++ b/dart/test/protocol/breadcrumb_test.dart @@ -2,6 +2,8 @@ import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; +// TODO(denis) + void main() { test('copyWith keeps unchanged', () { final data = _generate(); diff --git a/dart/test/protocol/browser_test.dart b/dart/test/protocol/browser_test.dart deleted file mode 100644 index d3123fb638..0000000000 --- a/dart/test/protocol/browser_test.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:sentry/sentry.dart'; -import 'package:test/test.dart'; - -void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - - final copy = data.copyWith(); - - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); - - test('copyWith takes new values', () { - final data = _generate(); - - final copy = data.copyWith( - name: 'name1', - version: 'version1', - ); - - expect('name1', copy.name); - expect('version1', copy.version); - }); -} - -SentryBrowser _generate() => SentryBrowser( - name: 'name', - version: 'version', - ); diff --git a/dart/test/protocol/contexts_test.dart b/dart/test/protocol/contexts_test.dart index 4533b26879..f59e92d905 100644 --- a/dart/test/protocol/contexts_test.dart +++ b/dart/test/protocol/contexts_test.dart @@ -2,6 +2,8 @@ import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; +// TODO(denis) + void main() { test('copyWith keeps unchanged', () { final data = _generate(); diff --git a/dart/test/protocol/device_test.dart b/dart/test/protocol/device_test.dart deleted file mode 100644 index fc78261df3..0000000000 --- a/dart/test/protocol/device_test.dart +++ /dev/null @@ -1,104 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:sentry/sentry.dart'; -import 'package:test/test.dart'; - -void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - - final copy = data.copyWith(); - - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); - - test('copyWith takes new values', () { - final data = _generate(); - - final bootTime = DateTime.now(); - - final copy = data.copyWith( - name: 'name1', - family: 'family1', - model: 'model1', - modelId: 'modelId1', - arch: 'arch1', - batteryLevel: 2, - orientation: SentryOrientation.portrait, - manufacturer: 'manufacturer1', - brand: 'brand1', - screenResolution: '123x3451', - screenDensity: 99.2, - screenDpi: 99, - online: true, - charging: false, - lowMemory: true, - simulator: false, - memorySize: 12345678, - freeMemory: 123456, - usableMemory: 98765, - storageSize: 12345678, - freeStorage: 12345678, - externalStorageSize: 987654, - externalFreeStorage: 987654, - bootTime: bootTime, - timezone: 'Austria/Vienna', - ); - - expect('name1', copy.name); - expect('family1', copy.family); - expect('model1', copy.model); - expect('modelId1', copy.modelId); - expect('arch1', copy.arch); - expect(2, copy.batteryLevel); - expect(SentryOrientation.portrait, copy.orientation); - expect('manufacturer1', copy.manufacturer); - expect('brand1', copy.brand); - expect('123x3451', copy.screenResolution); - expect(99.2, copy.screenDensity); - expect(99, copy.screenDpi); - expect(true, copy.online); - expect(false, copy.charging); - expect(true, copy.lowMemory); - expect(false, copy.simulator); - expect(12345678, copy.memorySize); - expect(123456, copy.freeMemory); - expect(98765, copy.usableMemory); - expect(12345678, copy.storageSize); - expect(12345678, copy.freeStorage); - expect(987654, copy.externalStorageSize); - expect(987654, copy.externalFreeStorage); - expect(bootTime, copy.bootTime); - expect('Austria/Vienna', copy.timezone); - }); -} - -SentryDevice _generate({DateTime? testBootTime}) => SentryDevice( - name: 'name', - family: 'family', - model: 'model', - modelId: 'modelId', - arch: 'arch', - batteryLevel: 1, - orientation: SentryOrientation.landscape, - manufacturer: 'manufacturer', - brand: 'brand', - screenResolution: '123x345', - screenDensity: 99.1, - screenDpi: 100, - online: false, - charging: true, - lowMemory: false, - simulator: true, - memorySize: 1234567, - freeMemory: 12345, - usableMemory: 9876, - storageSize: 1234567, - freeStorage: 1234567, - externalStorageSize: 98765, - externalFreeStorage: 98765, - bootTime: testBootTime ?? DateTime.now(), - timezone: 'Australia/Melbourne', - ); diff --git a/dart/test/protocol/gpu_test.dart b/dart/test/protocol/gpu_test.dart deleted file mode 100644 index 872632e4c0..0000000000 --- a/dart/test/protocol/gpu_test.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:sentry/sentry.dart'; -import 'package:test/test.dart'; - -void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - - final copy = data.copyWith(); - - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); - - test('copyWith takes new values', () { - final data = _generate(); - - final copy = data.copyWith( - name: 'name1', - id: 11, - vendorId: 22, - vendorName: 'vendorName1', - memorySize: 33, - apiType: 'apiType1', - multiThreadedRendering: false, - version: 'version1', - npotSupport: 'npotSupport1', - ); - - expect('name1', copy.name); - expect(11, copy.id); - expect(22, copy.vendorId); - expect('vendorName1', copy.vendorName); - expect(33, copy.memorySize); - expect('apiType1', copy.apiType); - expect(false, copy.multiThreadedRendering); - expect('version1', copy.version); - expect('npotSupport1', copy.npotSupport); - }); -} - -SentryGpu _generate() => SentryGpu( - name: 'name', - id: 1, - vendorId: 2, - vendorName: 'vendorName', - memorySize: 3, - apiType: 'apiType', - multiThreadedRendering: true, - version: 'version', - npotSupport: 'npotSupport', - ); diff --git a/dart/test/protocol/mechanism_test.dart b/dart/test/protocol/mechanism_test.dart index dc940dfc47..cee7d81e78 100644 --- a/dart/test/protocol/mechanism_test.dart +++ b/dart/test/protocol/mechanism_test.dart @@ -1,6 +1,8 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; +// TODO(denis) + void main() { test('copyWith keeps unchanged', () { final data = _generate(); diff --git a/dart/test/protocol/operating_system_test.dart b/dart/test/protocol/operating_system_test.dart deleted file mode 100644 index 33d51d5df1..0000000000 --- a/dart/test/protocol/operating_system_test.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:sentry/sentry.dart'; -import 'package:test/test.dart'; - -void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - - final copy = data.copyWith(); - - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); - - test('copyWith takes new values', () { - final data = _generate(); - - final copy = data.copyWith( - name: 'name1', - version: 'version1', - build: 'build1', - kernelVersion: 'kernelVersion1', - rooted: true, - ); - - expect('name1', copy.name); - expect('version1', copy.version); - expect('build1', copy.build); - expect('kernelVersion1', copy.kernelVersion); - expect(true, copy.rooted); - }); -} - -SentryOperatingSystem _generate() => SentryOperatingSystem( - name: 'name', - version: 'version', - build: 'build', - kernelVersion: 'kernelVersion', - rooted: false, - ); diff --git a/dart/test/protocol/sentry_app_test.dart b/dart/test/protocol/sentry_app_test.dart index 7738fef712..11defbcdb6 100644 --- a/dart/test/protocol/sentry_app_test.dart +++ b/dart/test/protocol/sentry_app_test.dart @@ -3,18 +3,16 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - final testStartTime = DateTime.fromMicrosecondsSinceEpoch(0); final sentryApp = SentryApp( - name: 'fixture-name', - version: 'fixture-version', - identifier: 'fixture-identifier', - build: 'fixture-build', - buildType: 'fixture-buildType', - startTime: testStartTime, - deviceAppHash: 'fixture-deviceAppHash' - ); + name: 'fixture-name', + version: 'fixture-version', + identifier: 'fixture-identifier', + build: 'fixture-build', + buildType: 'fixture-buildType', + startTime: testStartTime, + deviceAppHash: 'fixture-deviceAppHash'); final sentryAppJson = { 'app_name': 'fixture-name', @@ -26,26 +24,60 @@ void main() { 'device_app_hash': 'fixture-deviceAppHash' }; - test('toJson', () { - final json = sentryApp.toJson(); + group('json', () { + test('toJson', () { + final json = sentryApp.toJson(); - expect( - MapEquality().equals(sentryAppJson, json), - true, - ); + expect( + MapEquality().equals(sentryAppJson, json), + true, + ); + }); + test('fromJson', () { + final sentryApp = SentryApp.fromJson(sentryAppJson); + final json = sentryApp.toJson(); + + expect( + MapEquality().equals(sentryAppJson, json), + true, + ); + }); }); - test('fromJson', () { - final sentryApp = SentryApp.fromJson(sentryAppJson); - final json = sentryApp.toJson(); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryApp; - expect( - MapEquality().equals(sentryAppJson, json), - true, - ); - }); -} + final copy = data.copyWith(); + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + test('copyWith takes new values', () { + final data = sentryApp; + final startTime = DateTime.now(); + final copy = data.copyWith( + name: 'name1', + version: 'version1', + identifier: 'identifier1', + build: 'build1', + buildType: 'buildType1', + startTime: startTime, + deviceAppHash: 'hash1', + ); + + expect('name1', copy.name); + expect('version1', copy.version); + expect('identifier1', copy.identifier); + expect('build1', copy.build); + expect('buildType1', copy.buildType); + expect(startTime, copy.startTime); + expect('hash1', copy.deviceAppHash); + }); + }); +} diff --git a/dart/test/protocol/sentry_browser_test.dart b/dart/test/protocol/sentry_browser_test.dart index 76a54ad8da..93ca4ab114 100644 --- a/dart/test/protocol/sentry_browser_test.dart +++ b/dart/test/protocol/sentry_browser_test.dart @@ -3,7 +3,6 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - final sentryBrowser = SentryBrowser( name: 'fixture-name', version: 'fixture-version', @@ -33,4 +32,29 @@ void main() { ); }); }); + + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryBrowser; + + final copy = data.copyWith(); + + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + + test('copyWith takes new values', () { + final data = sentryBrowser; + + final copy = data.copyWith( + name: 'name1', + version: 'version1', + ); + + expect('name1', copy.name); + expect('version1', copy.version); + }); + }); } diff --git a/dart/test/protocol/sentry_device_test.dart b/dart/test/protocol/sentry_device_test.dart index 927163ab09..e704fbc1a5 100644 --- a/dart/test/protocol/sentry_device_test.dart +++ b/dart/test/protocol/sentry_device_test.dart @@ -80,4 +80,77 @@ void main() { ); }); }); + + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryDevice; + + final copy = data.copyWith(); + + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + + test('copyWith takes new values', () { + final data = sentryDevice; + + final bootTime = DateTime.now(); + + final copy = data.copyWith( + name: 'name1', + family: 'family1', + model: 'model1', + modelId: 'modelId1', + arch: 'arch1', + batteryLevel: 2, + orientation: SentryOrientation.portrait, + manufacturer: 'manufacturer1', + brand: 'brand1', + screenResolution: '123x3451', + screenDensity: 99.2, + screenDpi: 99, + online: true, + charging: false, + lowMemory: true, + simulator: false, + memorySize: 12345678, + freeMemory: 123456, + usableMemory: 98765, + storageSize: 12345678, + freeStorage: 12345678, + externalStorageSize: 987654, + externalFreeStorage: 987654, + bootTime: bootTime, + timezone: 'Austria/Vienna', + ); + + expect('name1', copy.name); + expect('family1', copy.family); + expect('model1', copy.model); + expect('modelId1', copy.modelId); + expect('arch1', copy.arch); + expect(2, copy.batteryLevel); + expect(SentryOrientation.portrait, copy.orientation); + expect('manufacturer1', copy.manufacturer); + expect('brand1', copy.brand); + expect('123x3451', copy.screenResolution); + expect(99.2, copy.screenDensity); + expect(99, copy.screenDpi); + expect(true, copy.online); + expect(false, copy.charging); + expect(true, copy.lowMemory); + expect(false, copy.simulator); + expect(12345678, copy.memorySize); + expect(123456, copy.freeMemory); + expect(98765, copy.usableMemory); + expect(12345678, copy.storageSize); + expect(12345678, copy.freeStorage); + expect(987654, copy.externalStorageSize); + expect(987654, copy.externalFreeStorage); + expect(bootTime, copy.bootTime); + expect('Austria/Vienna', copy.timezone); + }); + }); } diff --git a/dart/test/protocol/sentry_exception_test.dart b/dart/test/protocol/sentry_exception_test.dart index cad8cd4cba..a500a47534 100644 --- a/dart/test/protocol/sentry_exception_test.dart +++ b/dart/test/protocol/sentry_exception_test.dart @@ -1,6 +1,8 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; +// TODO(denis) + void main() { test('should serialize stacktrace', () { final mechanism = Mechanism( diff --git a/dart/test/protocol/sentry_gpu_test.dart b/dart/test/protocol/sentry_gpu_test.dart index 102c1b2771..c1e1c363b8 100644 --- a/dart/test/protocol/sentry_gpu_test.dart +++ b/dart/test/protocol/sentry_gpu_test.dart @@ -3,18 +3,16 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - final sentryGpu = SentryGpu( - name: 'fixture-name', - id: 1, - vendorId: 2, - vendorName: 'fixture-vendorName', - memorySize: 3, - apiType: 'fixture-apiType', - multiThreadedRendering: true, - version: '4', - npotSupport: 'fixture-npotSupport' - ); + name: 'fixture-name', + id: 1, + vendorId: 2, + vendorName: 'fixture-vendorName', + memorySize: 3, + apiType: 'fixture-apiType', + multiThreadedRendering: true, + version: '4', + npotSupport: 'fixture-npotSupport'); final sentryGpuJson = { 'name': 'fixture-name', @@ -47,4 +45,42 @@ void main() { ); }); }); + + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryGpu; + + final copy = data.copyWith(); + + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + test('copyWith takes new values', () { + final data = sentryGpu; + + final copy = data.copyWith( + name: 'name1', + id: 11, + vendorId: 22, + vendorName: 'vendorName1', + memorySize: 33, + apiType: 'apiType1', + multiThreadedRendering: false, + version: 'version1', + npotSupport: 'npotSupport1', + ); + + expect('name1', copy.name); + expect(11, copy.id); + expect(22, copy.vendorId); + expect('vendorName1', copy.vendorName); + expect(33, copy.memorySize); + expect('apiType1', copy.apiType); + expect(false, copy.multiThreadedRendering); + expect('version1', copy.version); + expect('npotSupport1', copy.npotSupport); + }); + }); } diff --git a/dart/test/protocol/sentry_operating_system_test.dart b/dart/test/protocol/sentry_operating_system_test.dart index 82c796d839..dee235712d 100644 --- a/dart/test/protocol/sentry_operating_system_test.dart +++ b/dart/test/protocol/sentry_operating_system_test.dart @@ -3,15 +3,13 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - final sentryOperatingSystem = SentryOperatingSystem( - name: 'fixture-name', - version: 'fixture-version', - build: 'fixture-build', - kernelVersion: 'fixture-kernelVersion', - rooted: true, - rawDescription: 'fixture-rawDescription' - ); + name: 'fixture-name', + version: 'fixture-version', + build: 'fixture-build', + kernelVersion: 'fixture-kernelVersion', + rooted: true, + rawDescription: 'fixture-rawDescription'); final sentryOperatingSystemJson = { 'name': 'fixture-name', @@ -32,7 +30,8 @@ void main() { ); }); test('fromJson', () { - final sentryOperatingSystem = SentryOperatingSystem.fromJson(sentryOperatingSystemJson); + final sentryOperatingSystem = + SentryOperatingSystem.fromJson(sentryOperatingSystemJson); final json = sentryOperatingSystem.toJson(); expect( @@ -41,4 +40,35 @@ void main() { ); }); }); + + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryOperatingSystem; + + final copy = data.copyWith(); + + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + + test('copyWith takes new values', () { + final data = sentryOperatingSystem; + + final copy = data.copyWith( + name: 'name1', + version: 'version1', + build: 'build1', + kernelVersion: 'kernelVersion1', + rooted: true, + ); + + expect('name1', copy.name); + expect('version1', copy.version); + expect('build1', copy.build); + expect('kernelVersion1', copy.kernelVersion); + expect(true, copy.rooted); + }); + }); } diff --git a/dart/test/protocol/user_test.dart b/dart/test/protocol/sentry_user_test.dart similarity index 98% rename from dart/test/protocol/user_test.dart rename to dart/test/protocol/sentry_user_test.dart index 8f0a080d52..3fd80ce696 100644 --- a/dart/test/protocol/user_test.dart +++ b/dart/test/protocol/sentry_user_test.dart @@ -1,6 +1,8 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; +// TODO(denis): test json + void main() { test('copyWith keeps unchanged', () { final data = _generate(); From 59b0eda6ebc776837c5cdb7c312ee22dbf6a080b Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 14:02:23 +0200 Subject: [PATCH 19/48] update todos --- dart/test/protocol/breadcrumb_test.dart | 65 ++++++++++--------- dart/test/protocol/contexts_test.dart | 2 +- dart/test/protocol/mechanism_test.dart | 2 +- dart/test/protocol/sentry_exception_test.dart | 2 +- 4 files changed, 36 insertions(+), 35 deletions(-) diff --git a/dart/test/protocol/breadcrumb_test.dart b/dart/test/protocol/breadcrumb_test.dart index f85931c4ab..25cf461c93 100644 --- a/dart/test/protocol/breadcrumb_test.dart +++ b/dart/test/protocol/breadcrumb_test.dart @@ -2,40 +2,41 @@ import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; -// TODO(denis) +// TODO(denis): test json void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - - final copy = data.copyWith(); - - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); - - test('copyWith takes new values', () { - final data = _generate(); - - final timestamp = DateTime.now(); - - final copy = data.copyWith( - message: 'message1', - timestamp: timestamp, - data: {'key1': 'value1'}, - level: SentryLevel.fatal, - category: 'category1', - type: 'type1', - ); - - expect('message1', copy.message); - expect(timestamp, copy.timestamp); - expect({'key1': 'value1'}, copy.data); - expect(SentryLevel.fatal, copy.level); - expect('category1', copy.category); - expect('type1', copy.type); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = _generate(); + + final copy = data.copyWith(); + + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + test('copyWith takes new values', () { + final data = _generate(); + + final timestamp = DateTime.now(); + + final copy = data.copyWith( + message: 'message1', + timestamp: timestamp, + data: {'key1': 'value1'}, + level: SentryLevel.fatal, + category: 'category1', + type: 'type1', + ); + + expect('message1', copy.message); + expect(timestamp, copy.timestamp); + expect({'key1': 'value1'}, copy.data); + expect(SentryLevel.fatal, copy.level); + expect('category1', copy.category); + expect('type1', copy.type); + }); }); } diff --git a/dart/test/protocol/contexts_test.dart b/dart/test/protocol/contexts_test.dart index f59e92d905..4a527ef4a6 100644 --- a/dart/test/protocol/contexts_test.dart +++ b/dart/test/protocol/contexts_test.dart @@ -2,7 +2,7 @@ import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; -// TODO(denis) +// TODO(denis): test json void main() { test('copyWith keeps unchanged', () { diff --git a/dart/test/protocol/mechanism_test.dart b/dart/test/protocol/mechanism_test.dart index cee7d81e78..d61067d911 100644 --- a/dart/test/protocol/mechanism_test.dart +++ b/dart/test/protocol/mechanism_test.dart @@ -1,7 +1,7 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; -// TODO(denis) +// TODO(denis): test json void main() { test('copyWith keeps unchanged', () { diff --git a/dart/test/protocol/sentry_exception_test.dart b/dart/test/protocol/sentry_exception_test.dart index a500a47534..18243415ff 100644 --- a/dart/test/protocol/sentry_exception_test.dart +++ b/dart/test/protocol/sentry_exception_test.dart @@ -1,7 +1,7 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; -// TODO(denis) +// TODO(denis): test json void main() { test('should serialize stacktrace', () { From aef3d686ff93c5d95419f00d277c9cd2b8912dde Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 14:11:19 +0200 Subject: [PATCH 20/48] implement breadcrumb test --- dart/lib/src/protocol/breadcrumb.dart | 4 +- dart/test/protocol/breadcrumb_test.dart | 56 +++++++++++++++++++------ 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/dart/lib/src/protocol/breadcrumb.dart b/dart/lib/src/protocol/breadcrumb.dart index ec55e699e3..46b5ce5489 100644 --- a/dart/lib/src/protocol/breadcrumb.dart +++ b/dart/lib/src/protocol/breadcrumb.dart @@ -79,7 +79,9 @@ class Breadcrumb { factory Breadcrumb.fromJson(Map json) { final levelName = json['level']?.toString(); return Breadcrumb( - timestamp: DateTime.now(), // TODO + timestamp: json['timestamp'] != null + ? DateTime.tryParse(json['timestamp']) + : null, message: json['message']?.toString(), category: json['category']?.toString(), data: json['data'] as Map?, diff --git a/dart/test/protocol/breadcrumb_test.dart b/dart/test/protocol/breadcrumb_test.dart index 25cf461c93..e34b8d2553 100644 --- a/dart/test/protocol/breadcrumb_test.dart +++ b/dart/test/protocol/breadcrumb_test.dart @@ -1,13 +1,52 @@ import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; - -// TODO(denis): test json +import 'package:sentry/src/utils.dart'; void main() { + final timestamp = DateTime.now(); + + final breadcrumb = Breadcrumb( + message: 'message', + timestamp: timestamp, + data: {'key': 'value'}, + level: SentryLevel.warning, + category: 'category', + type: 'type', + ); + + final breadcrumbJson = { + 'timestamp': formatDateAsIso8601WithMillisPrecision(timestamp), + 'message': 'message', + 'category': 'category', + 'data': {'key': 'value'}, + 'level': 'warning', + 'type': 'type', + }; + + group('json', () { + test('toJson', () { + final json = breadcrumb.toJson(); + + expect( + DeepCollectionEquality().equals(breadcrumbJson, json), + true, + ); + }); + test('fromJson', () { + final breadcrumb = Breadcrumb.fromJson(breadcrumbJson); + final json = breadcrumb.toJson(); + + expect( + DeepCollectionEquality().equals(breadcrumbJson, json), + true, + ); + }); + }); + group('copyWith', () { test('copyWith keeps unchanged', () { - final data = _generate(); + final data = breadcrumb; final copy = data.copyWith(); @@ -17,7 +56,7 @@ void main() { ); }); test('copyWith takes new values', () { - final data = _generate(); + final data = breadcrumb; final timestamp = DateTime.now(); @@ -39,12 +78,3 @@ void main() { }); }); } - -Breadcrumb _generate({DateTime? timestamp}) => Breadcrumb( - message: 'message', - timestamp: timestamp ?? DateTime.now(), - data: {'key': 'value'}, - level: SentryLevel.warning, - category: 'category', - type: 'type', - ); From 36eb8ec7fbfaea45549f3485c81a4159019b80eb Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 14:16:01 +0200 Subject: [PATCH 21/48] Add mechanism json tests --- dart/lib/src/protocol/mechanism.dart | 12 +++ dart/test/protocol/mechanism_test.dart | 102 ++++++++++++++++--------- 2 files changed, 78 insertions(+), 36 deletions(-) diff --git a/dart/lib/src/protocol/mechanism.dart b/dart/lib/src/protocol/mechanism.dart index 69b6e0320b..a7409b3602 100644 --- a/dart/lib/src/protocol/mechanism.dart +++ b/dart/lib/src/protocol/mechanism.dart @@ -74,6 +74,18 @@ class Mechanism { synthetic: synthetic ?? this.synthetic, ); + factory Mechanism.fromJson(Map json) { + return Mechanism( + type: json['type'], + description: json['description'], + helpLink: json['help_link'], + handled: json['handled'], + meta: json['meta'], + data: json['data'], + synthetic: json['synthetic'], + ); + } + Map toJson() { final json = {}; diff --git a/dart/test/protocol/mechanism_test.dart b/dart/test/protocol/mechanism_test.dart index d61067d911..4b484d2ca3 100644 --- a/dart/test/protocol/mechanism_test.dart +++ b/dart/test/protocol/mechanism_test.dart @@ -1,46 +1,76 @@ +import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; -// TODO(denis): test json - void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); + final mechanism = Mechanism( + type: 'type', + description: 'description', + helpLink: 'helpLink', + handled: true, + synthetic: true, + meta: {'key': 'value'}, + data: {'keyb': 'valueb'}, + ); + + final mechanismJson = { + 'type': 'type', + 'description': 'description', + 'help_link': 'helpLink', + 'handled': true, + 'meta': {'key': 'value'}, + 'data': {'keyb': 'valueb'}, + 'synthetic': true, + }; - final copy = data.copyWith(); + group('json', () { + test('toJson', () { + final json = mechanism.toJson(); - expect(data.toJson(), copy.toJson()); + expect( + DeepCollectionEquality().equals(mechanismJson, json), + true, + ); + }); + test('fromJson', () { + final mechanism = Mechanism.fromJson(mechanismJson); + final json = mechanism.toJson(); + + expect( + DeepCollectionEquality().equals(mechanismJson, json), + true, + ); + }); }); - test('copyWith takes new values', () { - final data = _generate(); - - final copy = data.copyWith( - type: 'type1', - description: 'description1', - helpLink: 'helpLink1', - handled: false, - synthetic: false, - meta: {'key1': 'value1'}, - data: {'keyb1': 'valueb1'}, - ); - - expect('type1', copy.type); - expect('description1', copy.description); - expect('helpLink1', copy.helpLink); - expect(false, copy.handled); - expect(false, copy.synthetic); - expect({'key1': 'value1'}, copy.meta); - expect({'keyb1': 'valueb1'}, copy.data); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = mechanism; + + final copy = data.copyWith(); + + expect(data.toJson(), copy.toJson()); + }); + test('copyWith takes new values', () { + final data = mechanism; + + final copy = data.copyWith( + type: 'type1', + description: 'description1', + helpLink: 'helpLink1', + handled: false, + synthetic: false, + meta: {'key1': 'value1'}, + data: {'keyb1': 'valueb1'}, + ); + + expect('type1', copy.type); + expect('description1', copy.description); + expect('helpLink1', copy.helpLink); + expect(false, copy.handled); + expect(false, copy.synthetic); + expect({'key1': 'value1'}, copy.meta); + expect({'keyb1': 'valueb1'}, copy.data); + }); }); } - -Mechanism _generate() => Mechanism( - type: 'type', - description: 'description', - helpLink: 'helpLink', - handled: true, - synthetic: true, - meta: {'key': 'value'}, - data: {'keyb': 'valueb'}, - ); From 649f5aab975b8b4db2f46dcce4c71dc6df1325ba Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 14:28:21 +0200 Subject: [PATCH 22/48] Implement SentryException test --- dart/lib/src/protocol/sentry_exception.dart | 17 +- dart/test/protocol/sentry_exception_test.dart | 246 ++++++++++-------- 2 files changed, 146 insertions(+), 117 deletions(-) diff --git a/dart/lib/src/protocol/sentry_exception.dart b/dart/lib/src/protocol/sentry_exception.dart index 76b0bfd5d2..8d48578146 100644 --- a/dart/lib/src/protocol/sentry_exception.dart +++ b/dart/lib/src/protocol/sentry_exception.dart @@ -33,14 +33,17 @@ class SentryException { }); factory SentryException.fromJson(Map json) { - final stackTraceJson = json['stacktrace'] as Map?; return SentryException( - type: json['type']?.toString(), - value: json['value']?.toString(), - module: json['module']?.toString(), - stackTrace: stackTraceJson != null - ? SentryStackTrace.fromJson(stackTraceJson) - : null + type: json['type'], + value: json['value'], + module: json['module'], + stackTrace: json['stacktrace'] != null + ? SentryStackTrace.fromJson(json['stacktrace']) + : null, + mechanism: json['mechanism'] != null + ? Mechanism.fromJson(json['mechanism']) + : null, + threadId: json['thread_id'] ); } diff --git a/dart/test/protocol/sentry_exception_test.dart b/dart/test/protocol/sentry_exception_test.dart index 18243415ff..15c75b0191 100644 --- a/dart/test/protocol/sentry_exception_test.dart +++ b/dart/test/protocol/sentry_exception_test.dart @@ -1,128 +1,154 @@ +import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; -// TODO(denis): test json - void main() { - test('should serialize stacktrace', () { - final mechanism = Mechanism( - type: 'mechanism-example', - description: 'a mechanism', - handled: true, - synthetic: false, - helpLink: 'https://help.com', - data: {'polyfill': 'bluebird'}, - meta: { + final sentryException = SentryException( + type: 'type', + value: 'value', + module: 'module', + stackTrace: SentryStackTrace(frames: [SentryStackFrame(absPath: 'abs')]), + mechanism: Mechanism(type: 'type'), + threadId: 1, + ); + + final sentryExceptionJson = { + 'type': 'type', + 'value': 'value', + 'module': 'module', + 'stacktrace': { + 'frames': [ + {'abs_path': 'abs'} + ] + }, + 'mechanism': {'type': 'type'}, + 'thread_id': 1, + }; + + group('json', () { + test('fromJson', () { + final sentryException = SentryException.fromJson(sentryExceptionJson); + final json = sentryException.toJson(); + + expect( + DeepCollectionEquality().equals(sentryExceptionJson, json), + true, + ); + }); + + test('should serialize stacktrace', () { + final mechanism = Mechanism( + type: 'mechanism-example', + description: 'a mechanism', + handled: true, + synthetic: false, + helpLink: 'https://help.com', + data: {'polyfill': 'bluebird'}, + meta: { + 'signal': { + 'number': 10, + 'code': 0, + 'name': 'SIGBUS', + 'code_name': 'BUS_NOOP' + } + }, + ); + final stacktrace = SentryStackTrace(frames: [ + SentryStackFrame( + absPath: 'frame-path', + fileName: 'example.dart', + function: 'parse', + module: 'example-module', + lineNo: 1, + colNo: 2, + contextLine: 'context-line example', + inApp: true, + package: 'example-package', + native: false, + platform: 'dart', + rawFunction: 'example-rawFunction', + framesOmitted: [1, 2, 3], + ), + ]); + + final sentryException = SentryException( + type: 'StateError', + value: 'Bad state: error', + module: 'example.module', + stackTrace: stacktrace, + mechanism: mechanism, + threadId: 123456, + ); + + final serialized = sentryException.toJson(); + + expect(serialized['type'], 'StateError'); + expect(serialized['value'], 'Bad state: error'); + expect(serialized['module'], 'example.module'); + expect(serialized['thread_id'], 123456); + expect(serialized['mechanism']['type'], 'mechanism-example'); + expect(serialized['mechanism']['description'], 'a mechanism'); + expect(serialized['mechanism']['handled'], true); + expect(serialized['mechanism']['synthetic'], false); + expect(serialized['mechanism']['help_link'], 'https://help.com'); + expect(serialized['mechanism']['data'], {'polyfill': 'bluebird'}); + expect(serialized['mechanism']['meta'], { 'signal': { 'number': 10, 'code': 0, 'name': 'SIGBUS', 'code_name': 'BUS_NOOP' } - }, - ); - final stacktrace = SentryStackTrace(frames: [ - SentryStackFrame( - absPath: 'frame-path', - fileName: 'example.dart', - function: 'parse', - module: 'example-module', - lineNo: 1, - colNo: 2, - contextLine: 'context-line example', - inApp: true, - package: 'example-package', - native: false, - platform: 'dart', - rawFunction: 'example-rawFunction', - framesOmitted: [1, 2, 3], - ), - ]); - - final sentryException = SentryException( - type: 'StateError', - value: 'Bad state: error', - module: 'example.module', - stackTrace: stacktrace, - mechanism: mechanism, - threadId: 123456, - ); - - final serialized = sentryException.toJson(); - - expect(serialized['type'], 'StateError'); - expect(serialized['value'], 'Bad state: error'); - expect(serialized['module'], 'example.module'); - expect(serialized['thread_id'], 123456); - expect(serialized['mechanism']['type'], 'mechanism-example'); - expect(serialized['mechanism']['description'], 'a mechanism'); - expect(serialized['mechanism']['handled'], true); - expect(serialized['mechanism']['synthetic'], false); - expect(serialized['mechanism']['help_link'], 'https://help.com'); - expect(serialized['mechanism']['data'], {'polyfill': 'bluebird'}); - expect(serialized['mechanism']['meta'], { - 'signal': { - 'number': 10, - 'code': 0, - 'name': 'SIGBUS', - 'code_name': 'BUS_NOOP' - } - }); + }); - final serializedFrame = serialized['stacktrace']['frames'].first; - expect(serializedFrame['abs_path'], 'frame-path'); - expect(serializedFrame['filename'], 'example.dart'); - expect(serializedFrame['function'], 'parse'); - expect(serializedFrame['module'], 'example-module'); - expect(serializedFrame['lineno'], 1); - expect(serializedFrame['colno'], 2); - expect(serializedFrame['context_line'], 'context-line example'); - expect(serializedFrame['in_app'], true); - expect(serializedFrame['package'], 'example-package'); - expect(serializedFrame['native'], false); - expect(serializedFrame['platform'], 'dart'); - expect(serializedFrame['raw_function'], 'example-rawFunction'); - expect(serializedFrame['frames_omitted'], [1, 2, 3]); + final serializedFrame = serialized['stacktrace']['frames'].first; + expect(serializedFrame['abs_path'], 'frame-path'); + expect(serializedFrame['filename'], 'example.dart'); + expect(serializedFrame['function'], 'parse'); + expect(serializedFrame['module'], 'example-module'); + expect(serializedFrame['lineno'], 1); + expect(serializedFrame['colno'], 2); + expect(serializedFrame['context_line'], 'context-line example'); + expect(serializedFrame['in_app'], true); + expect(serializedFrame['package'], 'example-package'); + expect(serializedFrame['native'], false); + expect(serializedFrame['platform'], 'dart'); + expect(serializedFrame['raw_function'], 'example-rawFunction'); + expect(serializedFrame['frames_omitted'], [1, 2, 3]); + }); }); - test('copyWith keeps unchanged', () { - final data = _generate(); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryException; - final copy = data.copyWith(); + final copy = data.copyWith(); - expect(data.toJson(), copy.toJson()); - }); + expect(data.toJson(), copy.toJson()); + }); + + test('copyWith takes new values', () { + final data = sentryException; - test('copyWith takes new values', () { - final data = _generate(); - - final stackTrace = - SentryStackTrace(frames: [SentryStackFrame(absPath: 'abs1')]); - final mechanism = Mechanism(type: 'type1'); - - final copy = data.copyWith( - type: 'type1', - value: 'value1', - module: 'module1', - stackTrace: stackTrace, - mechanism: mechanism, - threadId: 2, - ); - - expect('type1', copy.type); - expect('value1', copy.value); - expect('module1', copy.module); - expect(2, copy.threadId); - expect(mechanism.toJson(), copy.mechanism!.toJson()); - expect(stackTrace.toJson(), copy.stackTrace!.toJson()); + final stackTrace = + SentryStackTrace(frames: [SentryStackFrame(absPath: 'abs1')]); + final mechanism = Mechanism(type: 'type1'); + + final copy = data.copyWith( + type: 'type1', + value: 'value1', + module: 'module1', + stackTrace: stackTrace, + mechanism: mechanism, + threadId: 2, + ); + + expect('type1', copy.type); + expect('value1', copy.value); + expect('module1', copy.module); + expect(2, copy.threadId); + expect(mechanism.toJson(), copy.mechanism!.toJson()); + expect(stackTrace.toJson(), copy.stackTrace!.toJson()); + }); }); } - -SentryException _generate() => SentryException( - type: 'type', - value: 'value', - module: 'module', - stackTrace: SentryStackTrace(frames: [SentryStackFrame(absPath: 'abs')]), - mechanism: Mechanism(type: 'type'), - threadId: 1, - ); From 28728241a19c21319eeaad3df8893b4411111e5a Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 14:35:05 +0200 Subject: [PATCH 23/48] Add tests for SentryUser --- dart/test/protocol/sentry_user_test.dart | 133 ++++++++++++++--------- 1 file changed, 82 insertions(+), 51 deletions(-) diff --git a/dart/test/protocol/sentry_user_test.dart b/dart/test/protocol/sentry_user_test.dart index 3fd80ce696..4796ac0487 100644 --- a/dart/test/protocol/sentry_user_test.dart +++ b/dart/test/protocol/sentry_user_test.dart @@ -1,66 +1,97 @@ +import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; -// TODO(denis): test json - void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); - final copy = data.copyWith(); + final sentryUser = SentryUser( + id: 'id', + username: 'username', + email: 'email', + ipAddress: 'ipAddress', + extras: {'key': 'value'}, + ); - expect(data.toJson(), copy.toJson()); - }); + final sentryUserJson = { + 'id': 'id', + 'username': 'username', + 'email': 'email', + 'ip_address': 'ipAddress', + 'extras': {'key': 'value'}, + }; - test('copyWith takes new values', () { - final data = _generate(); - - final copy = data.copyWith( - id: 'id1', - username: 'username1', - email: 'email1', - ipAddress: 'ipAddress1', - extras: {'key1': 'value1'}, - ); - - expect('id1', copy.id); - expect('username1', copy.username); - expect('email1', copy.email); - expect('ipAddress1', copy.ipAddress); - expect({'key1': 'value1'}, copy.extras); - }); + group('json', () { + + test('toJson', () { + final json = sentryUser.toJson(); - test('toJson only serialises non-null values', () { - var data = SentryUser( - id: 'id', - ); + expect( + DeepCollectionEquality().equals(sentryUserJson, json), + true, + ); + }); + test('fromJson', () { + final sentryUser = SentryUser.fromJson(sentryUserJson); + final json = sentryUser.toJson(); - var json = data.toJson(); + expect( + DeepCollectionEquality().equals(sentryUserJson, json), + true, + ); + }); - expect(json.containsKey('id'), true); - expect(json.containsKey('username'), false); - expect(json.containsKey('email'), false); - expect(json.containsKey('ip_address'), false); - expect(json.containsKey('extras'), false); + test('toJson only serialises non-null values', () { + var data = SentryUser( + id: 'id', + ); - data = SentryUser( - ipAddress: 'ip', - ); + var json = data.toJson(); - json = data.toJson(); + expect(json.containsKey('id'), true); + expect(json.containsKey('username'), false); + expect(json.containsKey('email'), false); + expect(json.containsKey('ip_address'), false); + expect(json.containsKey('extras'), false); - expect(json.containsKey('id'), false); - expect(json.containsKey('username'), false); - expect(json.containsKey('email'), false); - expect(json.containsKey('ip_address'), true); - expect(json.containsKey('extras'), false); + data = SentryUser( + ipAddress: 'ip', + ); + + json = data.toJson(); + + expect(json.containsKey('id'), false); + expect(json.containsKey('username'), false); + expect(json.containsKey('email'), false); + expect(json.containsKey('ip_address'), true); + expect(json.containsKey('extras'), false); + }); }); -} -SentryUser _generate() => SentryUser( - id: 'id', - username: 'username', - email: 'email', - ipAddress: 'ipAddress', - extras: {'key': 'value'}, - ); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = sentryUser; + + final copy = data.copyWith(); + + expect(data.toJson(), copy.toJson()); + }); + + test('copyWith takes new values', () { + final data = sentryUser; + + final copy = data.copyWith( + id: 'id1', + username: 'username1', + email: 'email1', + ipAddress: 'ipAddress1', + extras: {'key1': 'value1'}, + ); + + expect('id1', copy.id); + expect('username1', copy.username); + expect('email1', copy.email); + expect('ipAddress1', copy.ipAddress); + expect({'key1': 'value1'}, copy.extras); + }); + }); +} From fbd80b5d451eaa0112a5b6e4a79080b109d396f5 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 15:15:37 +0200 Subject: [PATCH 24/48] Add json tests --- dart/test/protocol/contexts_test.dart | 153 ++++++++++++++++++-------- 1 file changed, 107 insertions(+), 46 deletions(-) diff --git a/dart/test/protocol/contexts_test.dart b/dart/test/protocol/contexts_test.dart index 4a527ef4a6..69a6f0133c 100644 --- a/dart/test/protocol/contexts_test.dart +++ b/dart/test/protocol/contexts_test.dart @@ -2,56 +2,117 @@ import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; -// TODO(denis): test json - void main() { - test('copyWith keeps unchanged', () { - final data = _generate(); + final contexts = Contexts( + device: SentryDevice(batteryLevel: 90), + operatingSystem: SentryOperatingSystem(name: 'name'), + runtimes: [SentryRuntime(name: 'name')], + app: SentryApp(name: 'name'), + browser: SentryBrowser(name: 'name'), + gpu: SentryGpu(id: 1), + ); + + final contextsJson = { + 'device': {'battery_level': 90.0}, + 'os': {'name': 'name'}, + 'runtime': {'name': 'name'}, + 'app': {'app_name': 'name'}, + 'browser': {'name': 'name'}, + 'gpu': {'id': 1}, + }; + + final contextsMutlipleRuntimes = Contexts( + runtimes: [ + SentryRuntime(name: 'name'), + SentryRuntime(name: 'name'), + SentryRuntime(key: 'key') + ], + ); + + final contextsMutlipleRuntimesJson = { + 'name': {'name': 'name', 'type': 'runtime'}, + 'name0': {'name': 'name', 'type': 'runtime'}, + }; + + group('json', () { + test('toJson', () { + final json = contexts.toJson(); + + expect( + DeepCollectionEquality().equals(contextsJson, json), + true, + ); + }); + test('toJson multiple runtimes', () { + final json = contextsMutlipleRuntimes.toJson(); + + expect( + DeepCollectionEquality().equals(contextsMutlipleRuntimesJson, json), + true, + ); + }); + test('fromJson', () { + final contexts = Contexts.fromJson(contextsJson); + final json = contexts.toJson(); - final copy = data.copyWith(); + expect( + DeepCollectionEquality().equals(contextsJson, json), + true, + ); + }); + test('fromJson multiple runtimes', () { + final contextsMutlipleRuntimes = Contexts.fromJson(contextsMutlipleRuntimesJson); + final json = contextsMutlipleRuntimes.toJson(); - // MapEquality fails for some reason, it probably check the instances equality too - expect(data.toJson(), copy.toJson()); + expect( + DeepCollectionEquality().equals(contextsMutlipleRuntimesJson, json), + true, + ); + }); }); - test('copyWith takes new values', () { - final data = _generate(); - data['extra'] = 'value'; - - final device = SentryDevice(batteryLevel: 100); - final os = SentryOperatingSystem(name: 'name1'); - final runtimes = [SentryRuntime(name: 'name1')]; - final app = SentryApp(name: 'name1'); - final browser = SentryBrowser(name: 'name1'); - final gpu = SentryGpu(id: 2); - - final copy = data.copyWith( - device: device, - operatingSystem: os, - runtimes: runtimes, - app: app, - browser: browser, - gpu: gpu, - ); - - expect(device.toJson(), copy.device!.toJson()); - expect(os.toJson(), copy.operatingSystem!.toJson()); - expect( - ListEquality().equals(runtimes, copy.runtimes), - true, - ); - expect(app.toJson(), copy.app!.toJson()); - expect(browser.toJson(), copy.browser!.toJson()); - expect(gpu.toJson(), copy.gpu!.toJson()); - expect('value', copy['extra']); + group('copyWith', () { + test('copyWith keeps unchanged', () { + final data = contexts; + + final copy = data.copyWith(); + + expect( + DeepCollectionEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); + + test('copyWith takes new values', () { + final data = contexts; + data['extra'] = 'value'; + + final device = SentryDevice(batteryLevel: 100); + final os = SentryOperatingSystem(name: 'name1'); + final runtimes = [SentryRuntime(name: 'name1')]; + final app = SentryApp(name: 'name1'); + final browser = SentryBrowser(name: 'name1'); + final gpu = SentryGpu(id: 2); + + final copy = data.copyWith( + device: device, + operatingSystem: os, + runtimes: runtimes, + app: app, + browser: browser, + gpu: gpu, + ); + + expect(device.toJson(), copy.device!.toJson()); + expect(os.toJson(), copy.operatingSystem!.toJson()); + expect( + ListEquality().equals(runtimes, copy.runtimes), + true, + ); + expect(app.toJson(), copy.app!.toJson()); + expect(browser.toJson(), copy.browser!.toJson()); + expect(gpu.toJson(), copy.gpu!.toJson()); + expect('value', copy['extra']); + }); }); } - -Contexts _generate() => Contexts( - device: SentryDevice(batteryLevel: 90), - operatingSystem: SentryOperatingSystem(name: 'name'), - runtimes: [SentryRuntime(name: 'name')], - app: SentryApp(name: 'name'), - browser: SentryBrowser(name: 'name'), - gpu: SentryGpu(id: 1), - ); From f15e269ec9890bd447ba9cd07f2f75a925bb057e Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 16:14:12 +0200 Subject: [PATCH 25/48] sentry event fromjson --- dart/lib/src/protocol/sentry_event.dart | 79 +++++++++++++++---------- dart/test/sentry_event_test.dart | 59 ++++++++++++++++++ 2 files changed, 107 insertions(+), 31 deletions(-) diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 5fb4facc8a..88db8e59d8 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -265,42 +265,59 @@ class SentryEvent { }); } + final fingerprintJson = json['fingerprint'] as List?; + final sdkVersionJson = json['sdk'] as Map?; + final messageJson = json['message'] as Map?; + final userJson = json['user'] as Map?; + final contextsJson = json['contexts'] as Map?; + final requestJson = json['request'] as Map?; + final debugMetaJson = json['debug_meta'] as Map?; + return SentryEvent( - eventId: SentryId.fromId(json['event_id']), // TODO: Hanled '-'? - timestamp: DateTime.now(), // TODO: Parse timestamp + eventId: SentryId.fromId(json['event_id']), + timestamp: json['timestamp'] != null + ? DateTime.tryParse(json['timestamp']) + : null, modules: modules, tags: tags, extra: json['extra'], - fingerprint: json['fingerprint']?.map((e) => e as String).toList(), + fingerprint: fingerprintJson?.toList(), breadcrumbs: breadcrumbs, - sdk: json['sdk'] != null ? SdkVersion.fromJson(json['sdk']) : null, - platform: json['platform']?.toString(), - logger: json['logger']?.toString(), - serverName: json['server_name']?.toString(), - release: json['release']?.toString(), - dist: json['dist']?.toString(), - environment: json['environment']?.toString(), - message: json['message'] != null - ? SentryMessage.fromJson(json['message']) - : null, - transaction: json['transaction']?.toString(), - stackTrace: stackTraceValuesStacktraceJson != null - ? SentryStackTrace.fromJson(stackTraceValuesStacktraceJson) - : null, - exception: exceptionValuesItemJson != null - ? SentryException.fromJson(exceptionValuesItemJson) - : null, - level: json['level'] != null ? SentryLevel.fromName(json['level']) : null, - culprit: json['culprit']?.toString(), - user: json['user'] != null ? SentryUser.fromJson(json['user']) : null, - contexts: - json['contexts'] != null ? Contexts.fromJson(json['contexts']) : null, - request: json['request'] != null - ? SentryRequest.fromJson(json['request']) - : null, - debugMeta: json['debug_meta'] != null - ? DebugMeta.fromJson(json['debug_meta']) - : null, + sdk: sdkVersionJson != null && sdkVersionJson.isNotEmpty + ? SdkVersion.fromJson(sdkVersionJson) + : null, + platform: json['platform'], + logger: json['logger'], + serverName: json['server_name'], + release: json['release'], + dist: json['dist'], + environment: json['environment'], + message: messageJson != null && messageJson.isNotEmpty + ? SentryMessage.fromJson(messageJson) + : null, + transaction: json['transaction'], + stackTrace: stackTraceValuesStacktraceJson != null && stackTraceValuesStacktraceJson.isNotEmpty + ? SentryStackTrace.fromJson(stackTraceValuesStacktraceJson) + : null, + exception: exceptionValuesItemJson != null && exceptionValuesItemJson.isNotEmpty + ? SentryException.fromJson(exceptionValuesItemJson) + : null, + level: json['level'] != null + ? SentryLevel.fromName(json['level']) + : null, + culprit: json['culprit'], + user: userJson != null && userJson.isNotEmpty + ? SentryUser.fromJson(userJson) + : null, + contexts: contextsJson != null && contextsJson.isNotEmpty + ? Contexts.fromJson(contextsJson) + : null, + request: requestJson != null && requestJson.isNotEmpty + ? SentryRequest.fromJson(requestJson) + : null, + debugMeta: debugMetaJson != null && debugMetaJson.isNotEmpty + ? DebugMeta.fromJson(debugMetaJson) + : null, ); } diff --git a/dart/test/sentry_event_test.dart b/dart/test/sentry_event_test.dart index 9c168ab2d7..35e0b4ba3f 100644 --- a/dart/test/sentry_event_test.dart +++ b/dart/test/sentry_event_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry/src/protocol/sentry_request.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; @@ -12,6 +13,64 @@ import 'package:test/test.dart'; import 'mocks.dart'; void main() { + group('deserialize', () { + final sentryId = SentryId.empty(); + final timestamp = DateTime.fromMillisecondsSinceEpoch(0); + final sentryEventJson = { + 'event_id': sentryId.toString(), + 'timestamp': formatDateAsIso8601WithMillisPrecision(timestamp), + 'platform': 'platform', + 'logger': 'logger', + 'server_name': 'serverName', + 'release': 'release', + 'dist': 'dist', + 'environment': 'environment', + 'modules': {'key': 'value'}, + 'message': {'formatted': 'formatted'}, + 'transaction': 'transaction', + 'exception': { + 'values': [ + {'type': 'type', 'value': 'value'} + ] + }, + 'level': 'debug', + 'culprit': 'culprit', + 'tags': {'key': 'value'}, + 'extra': {'key': 'value'}, + 'contexts': { + 'device': {'name': 'name'} + }, + 'user': { + 'id': 'id', + 'username': 'username', + 'ip_address': '192.168.0.0.1' + }, + 'fingerprint': ['fingerprint'], + 'breadcrumbs': [ + { + 'message': 'message', + 'timestamp': formatDateAsIso8601WithMillisPrecision(timestamp), + 'level': 'info' + } + ], + 'sdk': {'name': 'name', 'version': 'version'}, + 'request': {'url': 'url'}, + 'debug_meta': { + 'sdk_info': {'sdk_name': 'sdkName'} + }, + }; + + test('fromJson', () { + final sentryEvent = SentryEvent.fromJson(sentryEventJson); + final json = sentryEvent.toJson(); + + expect( + DeepCollectionEquality().equals(sentryEventJson, json), + true, + ); + }); + }); + group(SentryEvent, () { test('$Breadcrumb serializes', () { expect( From 37b1bc1b3ce8f74e4d40de212948ac2e009e7c99 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 16:21:05 +0200 Subject: [PATCH 26/48] fix failing tests --- dart/lib/src/protocol/sentry_event.dart | 4 ++-- dart/test/sentry_client_test.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 88db8e59d8..b1b83436c0 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -265,7 +265,7 @@ class SentryEvent { }); } - final fingerprintJson = json['fingerprint'] as List?; + final fingerprintJson = json['fingerprint'] as List?; final sdkVersionJson = json['sdk'] as Map?; final messageJson = json['message'] as Map?; final userJson = json['user'] as Map?; @@ -281,7 +281,7 @@ class SentryEvent { modules: modules, tags: tags, extra: json['extra'], - fingerprint: fingerprintJson?.toList(), + fingerprint: fingerprintJson?.map((e) => e as String).toList(), breadcrumbs: breadcrumbs, sdk: sdkVersionJson != null && sdkVersionJson.isNotEmpty ? SdkVersion.fromJson(sdkVersionJson) diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 6bd26b37a4..03fc184294 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -372,7 +372,7 @@ void main() { expect(capturedEvent.level!.name, SentryLevel.error.name); expect(capturedEvent.transaction, transaction); expect(capturedEvent.fingerprint, fingerprint); - expect(capturedEvent.breadcrumbs?.first, crumb); + expect(capturedEvent.breadcrumbs?.first.toJson(), crumb.toJson()); expect(capturedEvent.tags, { scopeTagKey: scopeTagValue, eventTagKey: eventTagValue, @@ -427,7 +427,7 @@ void main() { expect(capturedEvent.level!.name, SentryLevel.warning.name); expect(capturedEvent.transaction, eventTransaction); expect(capturedEvent.fingerprint, eventFingerprint); - expect(capturedEvent.breadcrumbs, eventCrumbs); + expect(capturedEvent.breadcrumbs?.map((e) => e.toJson()), eventCrumbs.map((e) => e.toJson())); }); }); From 688468de9c0b360a9da248b72943caf48d558464 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 20 Apr 2021 16:26:04 +0200 Subject: [PATCH 27/48] Run flutter format --- dart/lib/src/protocol/breadcrumb.dart | 4 +- dart/lib/src/protocol/contexts.dart | 2 +- dart/lib/src/protocol/debug_meta.dart | 6 +-- dart/lib/src/protocol/sdk_version.dart | 11 ++--- dart/lib/src/protocol/sentry_device.dart | 10 ++--- dart/lib/src/protocol/sentry_event.dart | 48 ++++++++++----------- dart/lib/src/protocol/sentry_exception.dart | 23 +++++----- dart/lib/src/protocol/sentry_message.dart | 8 ++-- dart/lib/src/transport/http_transport.dart | 2 +- dart/test/protocol/contexts_test.dart | 5 ++- dart/test/protocol/debug_meta_test.dart | 7 ++- dart/test/protocol/sdk_version_test.dart | 10 +++-- dart/test/protocol/sentry_browser_test.dart | 32 +++++++------- dart/test/protocol/sentry_package_test.dart | 1 - dart/test/protocol/sentry_runtime_test.dart | 17 ++++---- dart/test/protocol/sentry_user_test.dart | 4 +- dart/test/sentry_client_test.dart | 3 +- flutter/test/sentry_flutter_test.dart | 45 ++++++++++++------- 18 files changed, 124 insertions(+), 114 deletions(-) diff --git a/dart/lib/src/protocol/breadcrumb.dart b/dart/lib/src/protocol/breadcrumb.dart index 46b5ce5489..c7e9644971 100644 --- a/dart/lib/src/protocol/breadcrumb.dart +++ b/dart/lib/src/protocol/breadcrumb.dart @@ -80,8 +80,8 @@ class Breadcrumb { final levelName = json['level']?.toString(); return Breadcrumb( timestamp: json['timestamp'] != null - ? DateTime.tryParse(json['timestamp']) - : null, + ? DateTime.tryParse(json['timestamp']) + : null, message: json['message']?.toString(), category: json['category']?.toString(), data: json['data'] as Map?, diff --git a/dart/lib/src/protocol/contexts.dart b/dart/lib/src/protocol/contexts.dart index 4bd5055c8b..a1205e9650 100644 --- a/dart/lib/src/protocol/contexts.dart +++ b/dart/lib/src/protocol/contexts.dart @@ -103,7 +103,7 @@ class Contexts extends MapView { SentryGpu? get gpu => this[SentryGpu.type]; set gpu(SentryGpu? gpu) => this[SentryGpu.type] = gpu; - + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/debug_meta.dart b/dart/lib/src/protocol/debug_meta.dart index 9fef91508a..9127e2816b 100644 --- a/dart/lib/src/protocol/debug_meta.dart +++ b/dart/lib/src/protocol/debug_meta.dart @@ -25,9 +25,9 @@ class DebugMeta { sdk: sdkInfoJson != null ? SdkInfo.fromJson(sdkInfoJson) : null, images: debugImagesJson != null ? debugImagesJson - .map((debugImageJson) => DebugImage.fromJson( - debugImageJson as Map) - ).toList() + .map((debugImageJson) => + DebugImage.fromJson(debugImageJson as Map)) + .toList() : null); } diff --git a/dart/lib/src/protocol/sdk_version.dart b/dart/lib/src/protocol/sdk_version.dart index 3395032fc2..a495a8d837 100644 --- a/dart/lib/src/protocol/sdk_version.dart +++ b/dart/lib/src/protocol/sdk_version.dart @@ -68,11 +68,12 @@ class SdkVersion { final packagesJson = json['packages'] as List?; final integrationsJson = json['integrations'] as List?; return SdkVersion( - name: json['name'].toString(), - version: json['version'].toString(), - packages: packagesJson?.map((e) => SentryPackage.fromJson(e as Map)).toList(), - integrations: integrationsJson?.map((e) => e as String).toList() - ); + name: json['name'].toString(), + version: json['version'].toString(), + packages: packagesJson + ?.map((e) => SentryPackage.fromJson(e as Map)) + .toList(), + integrations: integrationsJson?.map((e) => e as String).toList()); } /// Produces a [Map] that can be serialized to JSON. diff --git a/dart/lib/src/protocol/sentry_device.dart b/dart/lib/src/protocol/sentry_device.dart index 7d8a304e14..6ff802dd96 100644 --- a/dart/lib/src/protocol/sentry_device.dart +++ b/dart/lib/src/protocol/sentry_device.dart @@ -45,11 +45,11 @@ class SentryDevice { modelId: data['model_id'], arch: data['arch'], batteryLevel: data['battery_level'], - orientation: data['orientation'] == 'portrait' - ? SentryOrientation.portrait - : data['orientation'] == 'landscape' - ? SentryOrientation.landscape - : null, + orientation: data['orientation'] == 'portrait' + ? SentryOrientation.portrait + : data['orientation'] == 'landscape' + ? SentryOrientation.landscape + : null, manufacturer: data['manufacturer'], brand: data['brand'], screenResolution: data['screen_resolution'], diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index b1b83436c0..635b04d67f 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -276,16 +276,16 @@ class SentryEvent { return SentryEvent( eventId: SentryId.fromId(json['event_id']), timestamp: json['timestamp'] != null - ? DateTime.tryParse(json['timestamp']) - : null, + ? DateTime.tryParse(json['timestamp']) + : null, modules: modules, tags: tags, extra: json['extra'], fingerprint: fingerprintJson?.map((e) => e as String).toList(), breadcrumbs: breadcrumbs, sdk: sdkVersionJson != null && sdkVersionJson.isNotEmpty - ? SdkVersion.fromJson(sdkVersionJson) - : null, + ? SdkVersion.fromJson(sdkVersionJson) + : null, platform: json['platform'], logger: json['logger'], serverName: json['server_name'], @@ -293,31 +293,31 @@ class SentryEvent { dist: json['dist'], environment: json['environment'], message: messageJson != null && messageJson.isNotEmpty - ? SentryMessage.fromJson(messageJson) - : null, + ? SentryMessage.fromJson(messageJson) + : null, transaction: json['transaction'], - stackTrace: stackTraceValuesStacktraceJson != null && stackTraceValuesStacktraceJson.isNotEmpty - ? SentryStackTrace.fromJson(stackTraceValuesStacktraceJson) - : null, - exception: exceptionValuesItemJson != null && exceptionValuesItemJson.isNotEmpty - ? SentryException.fromJson(exceptionValuesItemJson) - : null, - level: json['level'] != null - ? SentryLevel.fromName(json['level']) - : null, + stackTrace: stackTraceValuesStacktraceJson != null && + stackTraceValuesStacktraceJson.isNotEmpty + ? SentryStackTrace.fromJson(stackTraceValuesStacktraceJson) + : null, + exception: + exceptionValuesItemJson != null && exceptionValuesItemJson.isNotEmpty + ? SentryException.fromJson(exceptionValuesItemJson) + : null, + level: json['level'] != null ? SentryLevel.fromName(json['level']) : null, culprit: json['culprit'], user: userJson != null && userJson.isNotEmpty - ? SentryUser.fromJson(userJson) - : null, - contexts: contextsJson != null && contextsJson.isNotEmpty - ? Contexts.fromJson(contextsJson) - : null, + ? SentryUser.fromJson(userJson) + : null, + contexts: contextsJson != null && contextsJson.isNotEmpty + ? Contexts.fromJson(contextsJson) + : null, request: requestJson != null && requestJson.isNotEmpty - ? SentryRequest.fromJson(requestJson) - : null, + ? SentryRequest.fromJson(requestJson) + : null, debugMeta: debugMetaJson != null && debugMetaJson.isNotEmpty - ? DebugMeta.fromJson(debugMetaJson) - : null, + ? DebugMeta.fromJson(debugMetaJson) + : null, ); } diff --git a/dart/lib/src/protocol/sentry_exception.dart b/dart/lib/src/protocol/sentry_exception.dart index 8d48578146..9d63a564fa 100644 --- a/dart/lib/src/protocol/sentry_exception.dart +++ b/dart/lib/src/protocol/sentry_exception.dart @@ -34,19 +34,18 @@ class SentryException { factory SentryException.fromJson(Map json) { return SentryException( - type: json['type'], - value: json['value'], - module: json['module'], - stackTrace: json['stacktrace'] != null - ? SentryStackTrace.fromJson(json['stacktrace']) - : null, - mechanism: json['mechanism'] != null - ? Mechanism.fromJson(json['mechanism']) - : null, - threadId: json['thread_id'] - ); + type: json['type'], + value: json['value'], + module: json['module'], + stackTrace: json['stacktrace'] != null + ? SentryStackTrace.fromJson(json['stacktrace']) + : null, + mechanism: json['mechanism'] != null + ? Mechanism.fromJson(json['mechanism']) + : null, + threadId: json['thread_id']); } - + Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_message.dart b/dart/lib/src/protocol/sentry_message.dart index b8f9058fba..b63cd8d441 100644 --- a/dart/lib/src/protocol/sentry_message.dart +++ b/dart/lib/src/protocol/sentry_message.dart @@ -23,11 +23,9 @@ class SentryMessage { const SentryMessage(this.formatted, {this.template, this.params}); factory SentryMessage.fromJson(Map json) { - return SentryMessage( - json['formatted'].toString(), - template: json['message']?.toString(), - params: json['params'] as List? - ); + return SentryMessage(json['formatted'].toString(), + template: json['message']?.toString(), + params: json['params'] as List?); } Map toJson() { diff --git a/dart/lib/src/transport/http_transport.dart b/dart/lib/src/transport/http_transport.dart index 28100a4d6e..5d7528b457 100644 --- a/dart/lib/src/transport/http_transport.dart +++ b/dart/lib/src/transport/http_transport.dart @@ -42,7 +42,7 @@ class HttpTransport implements Transport { _options.clock, ); } - + @override Future send(SentryEnvelope envelope) async { final filteredEnvelope = _rateLimiter.filter(envelope); diff --git a/dart/test/protocol/contexts_test.dart b/dart/test/protocol/contexts_test.dart index 69a6f0133c..74687860dd 100644 --- a/dart/test/protocol/contexts_test.dart +++ b/dart/test/protocol/contexts_test.dart @@ -23,7 +23,7 @@ void main() { final contextsMutlipleRuntimes = Contexts( runtimes: [ - SentryRuntime(name: 'name'), + SentryRuntime(name: 'name'), SentryRuntime(name: 'name'), SentryRuntime(key: 'key') ], @@ -61,7 +61,8 @@ void main() { ); }); test('fromJson multiple runtimes', () { - final contextsMutlipleRuntimes = Contexts.fromJson(contextsMutlipleRuntimesJson); + final contextsMutlipleRuntimes = + Contexts.fromJson(contextsMutlipleRuntimesJson); final json = contextsMutlipleRuntimes.toJson(); expect( diff --git a/dart/test/protocol/debug_meta_test.dart b/dart/test/protocol/debug_meta_test.dart index 64dd3c5eb1..21caf02747 100644 --- a/dart/test/protocol/debug_meta_test.dart +++ b/dart/test/protocol/debug_meta_test.dart @@ -12,10 +12,9 @@ void main() { final debugMetaJson = { 'sdk_info': {'sdk_name': 'sdkName'}, - 'images': [{ - 'uuid': 'uuid', - 'type': 'macho' - }] + 'images': [ + {'uuid': 'uuid', 'type': 'macho'} + ] }; group('json', () { diff --git a/dart/test/protocol/sdk_version_test.dart b/dart/test/protocol/sdk_version_test.dart index a9189ee3e9..218ca72410 100644 --- a/dart/test/protocol/sdk_version_test.dart +++ b/dart/test/protocol/sdk_version_test.dart @@ -14,10 +14,12 @@ void main() { 'name': 'name', 'version': 'version', 'integrations': ['test'], - 'packages': [{ - 'name': 'name', - 'version': 'version', - }], + 'packages': [ + { + 'name': 'name', + 'version': 'version', + } + ], }; group('json', () { diff --git a/dart/test/protocol/sentry_browser_test.dart b/dart/test/protocol/sentry_browser_test.dart index 93ca4ab114..a388361ecd 100644 --- a/dart/test/protocol/sentry_browser_test.dart +++ b/dart/test/protocol/sentry_browser_test.dart @@ -35,26 +35,26 @@ void main() { group('copyWith', () { test('copyWith keeps unchanged', () { - final data = sentryBrowser; + final data = sentryBrowser; - final copy = data.copyWith(); + final copy = data.copyWith(); - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); - test('copyWith takes new values', () { - final data = sentryBrowser; + test('copyWith takes new values', () { + final data = sentryBrowser; - final copy = data.copyWith( - name: 'name1', - version: 'version1', - ); + final copy = data.copyWith( + name: 'name1', + version: 'version1', + ); - expect('name1', copy.name); - expect('version1', copy.version); - }); + expect('name1', copy.name); + expect('version1', copy.version); + }); }); } diff --git a/dart/test/protocol/sentry_package_test.dart b/dart/test/protocol/sentry_package_test.dart index 9e7ed0ccd8..b8c1d40e71 100644 --- a/dart/test/protocol/sentry_package_test.dart +++ b/dart/test/protocol/sentry_package_test.dart @@ -3,7 +3,6 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - final sentryPackage = SentryPackage( 'name', 'version', diff --git a/dart/test/protocol/sentry_runtime_test.dart b/dart/test/protocol/sentry_runtime_test.dart index caa747b070..578eb8c9a3 100644 --- a/dart/test/protocol/sentry_runtime_test.dart +++ b/dart/test/protocol/sentry_runtime_test.dart @@ -3,7 +3,6 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - final sentryRuntime = SentryRuntime( key: 'key', name: 'name', @@ -39,15 +38,15 @@ void main() { group('copyWith', () { test('copyWith keeps unchanged', () { - final data = sentryRuntime; + final data = sentryRuntime; - final copy = data.copyWith(); + final copy = data.copyWith(); - expect( - MapEquality().equals(data.toJson(), copy.toJson()), - true, - ); - }); + expect( + MapEquality().equals(data.toJson(), copy.toJson()), + true, + ); + }); test('copyWith takes new values', () { final data = sentryRuntime; @@ -64,5 +63,5 @@ void main() { expect('version1', copy.version); expect('rawDescription1', copy.rawDescription); }); - }); + }); } diff --git a/dart/test/protocol/sentry_user_test.dart b/dart/test/protocol/sentry_user_test.dart index 4796ac0487..297a949099 100644 --- a/dart/test/protocol/sentry_user_test.dart +++ b/dart/test/protocol/sentry_user_test.dart @@ -3,7 +3,6 @@ import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; void main() { - final sentryUser = SentryUser( id: 'id', username: 'username', @@ -21,7 +20,6 @@ void main() { }; group('json', () { - test('toJson', () { final json = sentryUser.toJson(); @@ -93,5 +91,5 @@ void main() { expect('ipAddress1', copy.ipAddress); expect({'key1': 'value1'}, copy.extras); }); - }); + }); } diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 03fc184294..7c8262983d 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -427,7 +427,8 @@ void main() { expect(capturedEvent.level!.name, SentryLevel.warning.name); expect(capturedEvent.transaction, eventTransaction); expect(capturedEvent.fingerprint, eventFingerprint); - expect(capturedEvent.breadcrumbs?.map((e) => e.toJson()), eventCrumbs.map((e) => e.toJson())); + expect(capturedEvent.breadcrumbs?.map((e) => e.toJson()), + eventCrumbs.map((e) => e.toJson())); }); }); diff --git a/flutter/test/sentry_flutter_test.dart b/flutter/test/sentry_flutter_test.dart index 138c6c3d2f..ba30d80f48 100644 --- a/flutter/test/sentry_flutter_test.dart +++ b/flutter/test/sentry_flutter_test.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; @@ -73,11 +74,12 @@ void main() { await Sentry.captureMessage('a message'); - final envelope = verify(transport.send(captureAny)).captured.first - as SentryEnvelope; + final envelope = + verify(transport.send(captureAny)).captured.first as SentryEnvelope; + final event = await eventFromEnvelope(envelope); - // expect(event.sdk!.integrations.length, 7); - // expect(event.sdk!.integrations.contains('loadContextsIntegration'), true); + expect(event.sdk!.integrations.length, 7); + expect(event.sdk!.integrations.contains('loadContextsIntegration'), true); }); test('should not add loadContextsIntegration if not ios', () async { @@ -92,13 +94,13 @@ void main() { await Sentry.captureMessage('a message'); - final envelope = verify(transport.send(captureAny)).captured.first - as SentryEnvelope; + final envelope = + verify(transport.send(captureAny)).captured.first as SentryEnvelope; + final event = await eventFromEnvelope(envelope); - // TODO - // expect(event.sdk!.integrations.length, 6); - // expect( - // event.sdk!.integrations.contains('loadContextsIntegration'), false); + expect(event.sdk!.integrations.length, 6); + expect( + event.sdk!.integrations.contains('loadContextsIntegration'), false); }); test('should not add loadAndroidImageListIntegration if not Android', @@ -114,13 +116,14 @@ void main() { await Sentry.captureMessage('a message'); - final envelope = verify(transport.send(captureAny)).captured.first - as SentryEnvelope; + final envelope = + verify(transport.send(captureAny)).captured.first as SentryEnvelope; + final event = await eventFromEnvelope(envelope); - // expect(event.sdk!.integrations.length, 6); - // expect( - // event.sdk!.integrations.contains('loadAndroidImageListIntegration'), - // false); + expect(event.sdk!.integrations.length, 6); + expect( + event.sdk!.integrations.contains('loadAndroidImageListIntegration'), + false); }); }); } @@ -135,3 +138,13 @@ Future loadTestPackage() async { buildNumber: 'buildNumber', ); } + +Future eventFromEnvelope(SentryEnvelope envelope) async { + final envelopeItemData = []; + await envelope.items.first + .envelopeItemStream() + .forEach(envelopeItemData.addAll); + final envelopeItem = utf8.decode(envelopeItemData); + final envelopeItemJson = jsonDecode(envelopeItem.split('\n').last); + return SentryEvent.fromJson(envelopeItemJson as Map); +} From b1756a8c7cab4c0c5fde414f899fb76545876191 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 09:52:56 +0200 Subject: [PATCH 28/48] Remove not needed type casts --- dart/lib/src/protocol/breadcrumb.dart | 8 ++++---- dart/lib/src/protocol/sdk_version.dart | 4 ++-- dart/lib/src/protocol/sentry_event.dart | 4 ++-- dart/lib/src/protocol/sentry_message.dart | 5 ++--- dart/lib/src/protocol/sentry_package.dart | 4 ++-- dart/lib/src/protocol/sentry_user.dart | 10 +++++----- dart/test/sentry_client_test.dart | 2 -- 7 files changed, 17 insertions(+), 20 deletions(-) diff --git a/dart/lib/src/protocol/breadcrumb.dart b/dart/lib/src/protocol/breadcrumb.dart index c7e9644971..a7dfe8a21b 100644 --- a/dart/lib/src/protocol/breadcrumb.dart +++ b/dart/lib/src/protocol/breadcrumb.dart @@ -77,16 +77,16 @@ class Breadcrumb { final DateTime timestamp; factory Breadcrumb.fromJson(Map json) { - final levelName = json['level']?.toString(); + final levelName = json['level']; return Breadcrumb( timestamp: json['timestamp'] != null ? DateTime.tryParse(json['timestamp']) : null, - message: json['message']?.toString(), - category: json['category']?.toString(), + message: json['message'], + category: json['category'], data: json['data'] as Map?, level: levelName != null ? SentryLevel.fromName(levelName) : null, - type: json['type']?.toString(), + type: json['type'], ); } diff --git a/dart/lib/src/protocol/sdk_version.dart b/dart/lib/src/protocol/sdk_version.dart index a495a8d837..2ab197ed97 100644 --- a/dart/lib/src/protocol/sdk_version.dart +++ b/dart/lib/src/protocol/sdk_version.dart @@ -68,8 +68,8 @@ class SdkVersion { final packagesJson = json['packages'] as List?; final integrationsJson = json['integrations'] as List?; return SdkVersion( - name: json['name'].toString(), - version: json['version'].toString(), + name: json['name'], + version: json['version'], packages: packagesJson ?.map((e) => SentryPackage.fromJson(e as Map)) .toList(), diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 635b04d67f..070ce5e23b 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -252,7 +252,7 @@ class SentryEvent { if (modulesJson != null) { modules = {}; modulesJson.forEach((key, value) { - modules?[key] = value as String; + modules?[key] = value; }); } @@ -261,7 +261,7 @@ class SentryEvent { if (tagsJson != null) { tags = {}; tagsJson.forEach((key, value) { - tags?[key] = value as String; + tags?[key] = value; }); } diff --git a/dart/lib/src/protocol/sentry_message.dart b/dart/lib/src/protocol/sentry_message.dart index b63cd8d441..fef6fc00c5 100644 --- a/dart/lib/src/protocol/sentry_message.dart +++ b/dart/lib/src/protocol/sentry_message.dart @@ -23,9 +23,8 @@ class SentryMessage { const SentryMessage(this.formatted, {this.template, this.params}); factory SentryMessage.fromJson(Map json) { - return SentryMessage(json['formatted'].toString(), - template: json['message']?.toString(), - params: json['params'] as List?); + return SentryMessage(json['formatted'], + template: json['message'], params: json['params']); } Map toJson() { diff --git a/dart/lib/src/protocol/sentry_package.dart b/dart/lib/src/protocol/sentry_package.dart index 52a67cabbf..c5ddc5b6e4 100644 --- a/dart/lib/src/protocol/sentry_package.dart +++ b/dart/lib/src/protocol/sentry_package.dart @@ -14,8 +14,8 @@ class SentryPackage { factory SentryPackage.fromJson(Map json) { return SentryPackage( - json['name'].toString(), - json['version'].toString(), + json['name'], + json['version'], ); } diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index 993bcb9d20..21e1032a19 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -55,11 +55,11 @@ class SentryUser { factory SentryUser.fromJson(Map json) { return SentryUser( - id: json['id']?.toString(), - username: json['username']?.toString(), - email: json['email']?.toString(), - ipAddress: json['ip_address']?.toString(), - extras: json['extras'] as Map?, + id: json['id'], + username: json['username'], + email: json['email'], + ipAddress: json['ip_address'], + extras: json['extras'], ); } diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 7c8262983d..950e33f75e 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -174,7 +174,6 @@ void main() { (options.transport as MockTransport).envelopes.first; final capturedEvent = await eventFromEnvelope(capturedEnvelope); - //expect(capturedEvent.throwable, error); // Cannot recreate insance from envelope... expect(capturedEvent.exception is SentryException, true); expect(capturedEvent.exception!.stackTrace, isNotNull); }); @@ -210,7 +209,6 @@ void main() { (options.transport as MockTransport).envelopes.first; final capturedEvent = await eventFromEnvelope(capturedEnvelope); - //expect(capturedEvent.throwable, error); // Cannot recreate insance from envelope... expect(capturedEvent.exception is SentryException, true); expect(capturedEvent.exception!.stackTrace, isNotNull); expect(capturedEvent.exception!.stackTrace!.frames.first.fileName, From 51d132f935d5b7b96200d54104482ad0aca5ec31 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 10:11:53 +0200 Subject: [PATCH 29/48] Document methods --- dart/lib/src/protocol/breadcrumb.dart | 1 + dart/lib/src/protocol/sdk_version.dart | 2 +- dart/lib/src/protocol/sentry_app.dart | 25 +++---- dart/lib/src/protocol/sentry_browser.dart | 11 +-- dart/lib/src/protocol/sentry_device.dart | 69 ++++++++++--------- dart/lib/src/protocol/sentry_event.dart | 1 + dart/lib/src/protocol/sentry_gpu.dart | 1 + .../src/protocol/sentry_operating_system.dart | 21 +++--- dart/lib/src/protocol/sentry_package.dart | 1 + dart/lib/src/protocol/sentry_runtime.dart | 13 ++-- dart/lib/src/protocol/sentry_stack_frame.dart | 1 + dart/lib/src/protocol/sentry_user.dart | 1 + 12 files changed, 79 insertions(+), 68 deletions(-) diff --git a/dart/lib/src/protocol/breadcrumb.dart b/dart/lib/src/protocol/breadcrumb.dart index a7dfe8a21b..883044f8e6 100644 --- a/dart/lib/src/protocol/breadcrumb.dart +++ b/dart/lib/src/protocol/breadcrumb.dart @@ -76,6 +76,7 @@ class Breadcrumb { /// The value is submitted to Sentry with second precision. final DateTime timestamp; + /// Creates a [Breadcrumb] from deserialized JSON [Map]. factory Breadcrumb.fromJson(Map json) { final levelName = json['level']; return Breadcrumb( diff --git a/dart/lib/src/protocol/sdk_version.dart b/dart/lib/src/protocol/sdk_version.dart index 2ab197ed97..37355d7613 100644 --- a/dart/lib/src/protocol/sdk_version.dart +++ b/dart/lib/src/protocol/sdk_version.dart @@ -63,7 +63,7 @@ class SdkVersion { String get identifier => '$name/$version'; - /// Produces a [SdkVersion] from deserialiazed JSON [Map]. + /// Deserializes a [SdkVersion] from JSON [Map]. factory SdkVersion.fromJson(Map json) { final packagesJson = json['packages'] as List?; final integrationsJson = json['integrations'] as List?; diff --git a/dart/lib/src/protocol/sentry_app.dart b/dart/lib/src/protocol/sentry_app.dart index 1e4c87ecbe..90581e1fb4 100644 --- a/dart/lib/src/protocol/sentry_app.dart +++ b/dart/lib/src/protocol/sentry_app.dart @@ -18,18 +18,6 @@ class SentryApp { this.deviceAppHash, }); - factory SentryApp.fromJson(Map data) => SentryApp( - name: data['app_name'], - version: data['app_version'], - identifier: data['app_identifier'], - build: data['app_build'], - buildType: data['build_type'], - startTime: data['app_start_time'] != null - ? DateTime.tryParse(data['app_start_time']) - : null, - deviceAppHash: data['device_app_hash'], - ); - /// Human readable application name, as it appears on the platform. final String? name; @@ -51,6 +39,19 @@ class SentryApp { /// Application specific device identifier. final String? deviceAppHash; + /// Deserializes a [SentryApp] from JSON [Map]. + factory SentryApp.fromJson(Map data) => SentryApp( + name: data['app_name'], + version: data['app_version'], + identifier: data['app_identifier'], + build: data['app_build'], + buildType: data['build_type'], + startTime: data['app_start_time'] != null + ? DateTime.tryParse(data['app_start_time']) + : null, + deviceAppHash: data['device_app_hash'], + ); + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_browser.dart b/dart/lib/src/protocol/sentry_browser.dart index 32038bf2a4..5c536d5819 100644 --- a/dart/lib/src/protocol/sentry_browser.dart +++ b/dart/lib/src/protocol/sentry_browser.dart @@ -11,17 +11,18 @@ class SentryBrowser { /// Creates an instance of [SentryBrowser]. const SentryBrowser({this.name, this.version}); - factory SentryBrowser.fromJson(Map data) => SentryBrowser( - name: data['name'], - version: data['version'], - ); - /// Human readable application name, as it appears on the platform. final String? name; /// Human readable application version, as it appears on the platform. final String? version; + /// Deserializes a [SentryBrowser] from JSON [Map]. + factory SentryBrowser.fromJson(Map data) => SentryBrowser( + name: data['name'], + version: data['version'], + ); + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_device.dart b/dart/lib/src/protocol/sentry_device.dart index 6ff802dd96..b16b0294c3 100644 --- a/dart/lib/src/protocol/sentry_device.dart +++ b/dart/lib/src/protocol/sentry_device.dart @@ -38,40 +38,6 @@ class SentryDevice { batteryLevel == null || (batteryLevel >= 0 && batteryLevel <= 100), ); - factory SentryDevice.fromJson(Map data) => SentryDevice( - name: data['name'], - family: data['family'], - model: data['model'], - modelId: data['model_id'], - arch: data['arch'], - batteryLevel: data['battery_level'], - orientation: data['orientation'] == 'portrait' - ? SentryOrientation.portrait - : data['orientation'] == 'landscape' - ? SentryOrientation.landscape - : null, - manufacturer: data['manufacturer'], - brand: data['brand'], - screenResolution: data['screen_resolution'], - screenDensity: data['screen_density'], - screenDpi: data['screen_dpi'], - online: data['online'], - charging: data['charging'], - lowMemory: data['low_memory'], - simulator: data['simulator'], - memorySize: data['memory_size'], - freeMemory: data['free_memory'], - usableMemory: data['usable_memory'], - storageSize: data['storage_size'], - freeStorage: data['free_storage'], - externalStorageSize: data['external_storage_size'], - externalFreeStorage: data['external_free_storage'], - bootTime: data['boot_time'] != null - ? DateTime.tryParse(data['boot_time']) - : null, - timezone: data['timezone'], - ); - /// The name of the device. This is typically a hostname. final String? name; @@ -154,6 +120,41 @@ class SentryDevice { /// The timezone of the device, e.g.: `Europe/Vienna`. final String? timezone; + /// Deserializes a [SentryDevice] from JSON [Map]. + factory SentryDevice.fromJson(Map data) => SentryDevice( + name: data['name'], + family: data['family'], + model: data['model'], + modelId: data['model_id'], + arch: data['arch'], + batteryLevel: data['battery_level'], + orientation: data['orientation'] == 'portrait' + ? SentryOrientation.portrait + : data['orientation'] == 'landscape' + ? SentryOrientation.landscape + : null, + manufacturer: data['manufacturer'], + brand: data['brand'], + screenResolution: data['screen_resolution'], + screenDensity: data['screen_density'], + screenDpi: data['screen_dpi'], + online: data['online'], + charging: data['charging'], + lowMemory: data['low_memory'], + simulator: data['simulator'], + memorySize: data['memory_size'], + freeMemory: data['free_memory'], + usableMemory: data['usable_memory'], + storageSize: data['storage_size'], + freeStorage: data['free_storage'], + externalStorageSize: data['external_storage_size'], + externalFreeStorage: data['external_free_storage'], + bootTime: data['boot_time'] != null + ? DateTime.tryParse(data['boot_time']) + : null, + timezone: data['timezone'], + ); + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 070ce5e23b..389cc0868a 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -226,6 +226,7 @@ class SentryEvent { debugMeta: debugMeta ?? this.debugMeta, ); + /// Deserializes a [SentryEvent] from JSON [Map]. factory SentryEvent.fromJson(Map json) { final breadcrumbsJson = json['breadcrumbs'] as List?; final breadcrumbs = breadcrumbsJson?.map((e) { diff --git a/dart/lib/src/protocol/sentry_gpu.dart b/dart/lib/src/protocol/sentry_gpu.dart index bba5cfe07b..6696f7b4f7 100644 --- a/dart/lib/src/protocol/sentry_gpu.dart +++ b/dart/lib/src/protocol/sentry_gpu.dart @@ -56,6 +56,7 @@ class SentryGpu { this.npotSupport, }); + /// Deserializes a [SentryGpu] from JSON [Map]. factory SentryGpu.fromJson(Map data) => SentryGpu( name: data['name'], id: data['id'], diff --git a/dart/lib/src/protocol/sentry_operating_system.dart b/dart/lib/src/protocol/sentry_operating_system.dart index 60d7ce6848..4b6376a405 100644 --- a/dart/lib/src/protocol/sentry_operating_system.dart +++ b/dart/lib/src/protocol/sentry_operating_system.dart @@ -17,16 +17,6 @@ class SentryOperatingSystem { this.rawDescription, }); - factory SentryOperatingSystem.fromJson(Map data) => - SentryOperatingSystem( - name: data['name'], - version: data['version'], - build: data['build'], - kernelVersion: data['kernel_version'], - rooted: data['rooted'], - rawDescription: data['raw_description'], - ); - /// The name of the operating system. final String? name; @@ -50,6 +40,17 @@ class SentryOperatingSystem { /// version from this string, if they are not explicitly given. final String? rawDescription; + /// Deserializes a [SentryOperatingSystem] from JSON [Map]. + factory SentryOperatingSystem.fromJson(Map data) => + SentryOperatingSystem( + name: data['name'], + version: data['version'], + build: data['build'], + kernelVersion: data['kernel_version'], + rooted: data['rooted'], + rawDescription: data['raw_description'], + ); + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_package.dart b/dart/lib/src/protocol/sentry_package.dart index c5ddc5b6e4..51fad73377 100644 --- a/dart/lib/src/protocol/sentry_package.dart +++ b/dart/lib/src/protocol/sentry_package.dart @@ -12,6 +12,7 @@ class SentryPackage { /// The version of the SDK. final String version; + /// Deserializes a [SentryPackage] from JSON [Map]. factory SentryPackage.fromJson(Map json) { return SentryPackage( json['name'], diff --git a/dart/lib/src/protocol/sentry_runtime.dart b/dart/lib/src/protocol/sentry_runtime.dart index 54bf50a266..6bba34ff8c 100644 --- a/dart/lib/src/protocol/sentry_runtime.dart +++ b/dart/lib/src/protocol/sentry_runtime.dart @@ -13,12 +13,6 @@ class SentryRuntime { const SentryRuntime({this.key, this.name, this.version, this.rawDescription}) : assert(key == null || key.length >= 1); - factory SentryRuntime.fromJson(Map data) => SentryRuntime( - name: data['name'], - version: data['version'], - rawDescription: data['raw_description'], - ); - /// Key used in the JSON and which will be displayed /// in the Sentry UI. Defaults to lower case version of [name]. /// @@ -37,6 +31,13 @@ class SentryRuntime { /// and version from this string, if they are not explicitly given. final String? rawDescription; + /// Deserializes a [SentryRuntime] from JSON [Map]. + factory SentryRuntime.fromJson(Map data) => SentryRuntime( + name: data['name'], + version: data['version'], + rawDescription: data['raw_description'], + ); + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_stack_frame.dart b/dart/lib/src/protocol/sentry_stack_frame.dart index 0c761cd60a..3620c9546d 100644 --- a/dart/lib/src/protocol/sentry_stack_frame.dart +++ b/dart/lib/src/protocol/sentry_stack_frame.dart @@ -108,6 +108,7 @@ class SentryStackFrame { /// The original function name, if the function name is shortened or demangled. Sentry shows the raw function when clicking on the shortened one in the UI. final String? rawFunction; + /// Deserializes a [SentryStackFrame] from JSON [Map]. factory SentryStackFrame.fromJson(Map json) { return SentryStackFrame( absPath: json['abs_path'], diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index 21e1032a19..54d363e0b7 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -53,6 +53,7 @@ class SentryUser { /// by Sentry. final Map? extras; + /// Deserializes a [SentryUser] from JSON [Map]. factory SentryUser.fromJson(Map json) { return SentryUser( id: json['id'], From 3ae6654e89728cf1dae8f79008299de6517c2c74 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 11:19:39 +0200 Subject: [PATCH 30/48] Use switch instead of ifs --- dart/lib/src/protocol/sentry_level.dart | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/dart/lib/src/protocol/sentry_level.dart b/dart/lib/src/protocol/sentry_level.dart index 6be45655fb..72f4a0a1e3 100644 --- a/dart/lib/src/protocol/sentry_level.dart +++ b/dart/lib/src/protocol/sentry_level.dart @@ -16,16 +16,16 @@ class SentryLevel { final int ordinal; factory SentryLevel.fromName(String name) { - if (name == 'fatal') { - return SentryLevel.fatal; - } else if (name == 'error') { - return SentryLevel.error; - } else if (name == 'warning') { - return SentryLevel.warning; - } else if (name == 'info') { - return SentryLevel.info; - } else { - return SentryLevel.debug; + switch (name) { + case 'fatal': + return SentryLevel.fatal; + case 'error': + return SentryLevel.error; + case 'warning': + return SentryLevel.warning; + case 'info': + return SentryLevel.info; } + return SentryLevel.debug; } } From b1fbd1a211bbddafb4a9c0661e1f3d42d9f32925 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 11:25:23 +0200 Subject: [PATCH 31/48] Update method documentation --- dart/lib/src/protocol/breadcrumb.dart | 2 +- dart/lib/src/protocol/contexts.dart | 1 + dart/lib/src/protocol/debug_image.dart | 2 ++ dart/lib/src/protocol/debug_meta.dart | 2 ++ dart/lib/src/protocol/mechanism.dart | 2 ++ dart/lib/src/protocol/sdk_info.dart | 2 ++ dart/lib/src/protocol/sentry_exception.dart | 2 ++ dart/lib/src/protocol/sentry_message.dart | 2 ++ dart/lib/src/protocol/sentry_request.dart | 2 ++ dart/lib/src/protocol/sentry_stack_frame.dart | 1 + dart/lib/src/protocol/sentry_stack_trace.dart | 2 ++ 11 files changed, 19 insertions(+), 1 deletion(-) diff --git a/dart/lib/src/protocol/breadcrumb.dart b/dart/lib/src/protocol/breadcrumb.dart index 883044f8e6..d7eeb74994 100644 --- a/dart/lib/src/protocol/breadcrumb.dart +++ b/dart/lib/src/protocol/breadcrumb.dart @@ -76,7 +76,7 @@ class Breadcrumb { /// The value is submitted to Sentry with second precision. final DateTime timestamp; - /// Creates a [Breadcrumb] from deserialized JSON [Map]. + /// Deserializes a [Breadcrumb] from JSON [Map]. factory Breadcrumb.fromJson(Map json) { final levelName = json['level']; return Breadcrumb( diff --git a/dart/lib/src/protocol/contexts.dart b/dart/lib/src/protocol/contexts.dart index a1205e9650..d7b8586515 100644 --- a/dart/lib/src/protocol/contexts.dart +++ b/dart/lib/src/protocol/contexts.dart @@ -25,6 +25,7 @@ class Contexts extends MapView { SentryGpu.type: gpu, }); + /// Deserializes [Contexts] from JSON [Map]. factory Contexts.fromJson(Map data) { final contexts = Contexts( device: data[SentryDevice.type] != null diff --git a/dart/lib/src/protocol/debug_image.dart b/dart/lib/src/protocol/debug_image.dart index 3017cb0c4c..b75dea5bb0 100644 --- a/dart/lib/src/protocol/debug_image.dart +++ b/dart/lib/src/protocol/debug_image.dart @@ -50,6 +50,7 @@ class DebugImage { this.codeId, }); + /// Deserializes a [DebugImage] from JSON [Map]. factory DebugImage.fromJson(Map json) { return DebugImage( type: json['type'], @@ -64,6 +65,7 @@ class DebugImage { ); } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/debug_meta.dart b/dart/lib/src/protocol/debug_meta.dart index 9127e2816b..f80ce5a44b 100644 --- a/dart/lib/src/protocol/debug_meta.dart +++ b/dart/lib/src/protocol/debug_meta.dart @@ -18,6 +18,7 @@ class DebugMeta { DebugMeta({this.sdk, List? images}) : _images = images; + /// Deserializes a [DebugMeta] from JSON [Map]. factory DebugMeta.fromJson(Map json) { final sdkInfoJson = json['sdk_info']; final debugImagesJson = json['images'] as List?; @@ -31,6 +32,7 @@ class DebugMeta { : null); } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/mechanism.dart b/dart/lib/src/protocol/mechanism.dart index a7409b3602..8d8977b97c 100644 --- a/dart/lib/src/protocol/mechanism.dart +++ b/dart/lib/src/protocol/mechanism.dart @@ -74,6 +74,7 @@ class Mechanism { synthetic: synthetic ?? this.synthetic, ); + /// Deserializes a [Mechanism] from JSON [Map]. factory Mechanism.fromJson(Map json) { return Mechanism( type: json['type'], @@ -86,6 +87,7 @@ class Mechanism { ); } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sdk_info.dart b/dart/lib/src/protocol/sdk_info.dart index 7e3ce1fd73..a3434afd83 100644 --- a/dart/lib/src/protocol/sdk_info.dart +++ b/dart/lib/src/protocol/sdk_info.dart @@ -15,6 +15,7 @@ class SdkInfo { this.versionPatchlevel, }); + /// Deserializes a [SdkInfo] from JSON [Map]. factory SdkInfo.fromJson(Map json) { return SdkInfo( sdkName: json['sdk_name'], @@ -24,6 +25,7 @@ class SdkInfo { ); } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; if (sdkName != null) { diff --git a/dart/lib/src/protocol/sentry_exception.dart b/dart/lib/src/protocol/sentry_exception.dart index 9d63a564fa..3297713db3 100644 --- a/dart/lib/src/protocol/sentry_exception.dart +++ b/dart/lib/src/protocol/sentry_exception.dart @@ -32,6 +32,7 @@ class SentryException { this.threadId, }); + /// Deserializes a [SentryException] from JSON [Map]. factory SentryException.fromJson(Map json) { return SentryException( type: json['type'], @@ -46,6 +47,7 @@ class SentryException { threadId: json['thread_id']); } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_message.dart b/dart/lib/src/protocol/sentry_message.dart index fef6fc00c5..2c2a4176b0 100644 --- a/dart/lib/src/protocol/sentry_message.dart +++ b/dart/lib/src/protocol/sentry_message.dart @@ -22,11 +22,13 @@ class SentryMessage { const SentryMessage(this.formatted, {this.template, this.params}); + /// Deserializes a [SentryMessage] from JSON [Map]. factory SentryMessage.fromJson(Map json) { return SentryMessage(json['formatted'], template: json['message'], params: json['params']); } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_request.dart b/dart/lib/src/protocol/sentry_request.dart index 2edc11b1b3..7c326df727 100644 --- a/dart/lib/src/protocol/sentry_request.dart +++ b/dart/lib/src/protocol/sentry_request.dart @@ -69,6 +69,7 @@ class SentryRequest { _env = env != null ? Map.from(env) : null, _other = other != null ? Map.from(other) : null; + /// Deserializes a [SentryRequest] from JSON [Map]. factory SentryRequest.fromJson(Map json) { return SentryRequest( url: json['url'], @@ -82,6 +83,7 @@ class SentryRequest { ); } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_stack_frame.dart b/dart/lib/src/protocol/sentry_stack_frame.dart index 3620c9546d..27085f8522 100644 --- a/dart/lib/src/protocol/sentry_stack_frame.dart +++ b/dart/lib/src/protocol/sentry_stack_frame.dart @@ -133,6 +133,7 @@ class SentryStackFrame { ); } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; diff --git a/dart/lib/src/protocol/sentry_stack_trace.dart b/dart/lib/src/protocol/sentry_stack_trace.dart index 719e3477df..2330f7af03 100644 --- a/dart/lib/src/protocol/sentry_stack_trace.dart +++ b/dart/lib/src/protocol/sentry_stack_trace.dart @@ -25,6 +25,7 @@ class SentryStackTrace { /// thus mapping to the last frame in the list. Map get registers => Map.unmodifiable(_registers ?? const {}); + /// Deserializes a [SentryStackTrace] from JSON [Map]. factory SentryStackTrace.fromJson(Map json) { final framesJson = json['frames'] as List?; return SentryStackTrace( @@ -36,6 +37,7 @@ class SentryStackTrace { registers: json['registers'] as Map?); } + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; From 9d7c0177559090d3c9861879e9ecebf12564c160 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 11:55:58 +0200 Subject: [PATCH 32/48] Add json access feedback --- dart/lib/src/protocol/breadcrumb.dart | 7 ++-- dart/lib/src/protocol/debug_meta.dart | 10 +++--- dart/lib/src/protocol/sdk_version.dart | 3 +- dart/lib/src/protocol/sentry_event.dart | 23 ++++++------- dart/lib/src/protocol/sentry_exception.dart | 13 ++++--- dart/lib/src/protocol/sentry_message.dart | 7 ++-- dart/lib/src/protocol/sentry_stack_trace.dart | 3 +- dart/test/sentry_event_test.dart | 34 +++++++++++++++++++ 8 files changed, 69 insertions(+), 31 deletions(-) diff --git a/dart/lib/src/protocol/breadcrumb.dart b/dart/lib/src/protocol/breadcrumb.dart index d7eeb74994..7259d58121 100644 --- a/dart/lib/src/protocol/breadcrumb.dart +++ b/dart/lib/src/protocol/breadcrumb.dart @@ -79,13 +79,14 @@ class Breadcrumb { /// Deserializes a [Breadcrumb] from JSON [Map]. factory Breadcrumb.fromJson(Map json) { final levelName = json['level']; + final timestamp = json['timestamp']; return Breadcrumb( - timestamp: json['timestamp'] != null - ? DateTime.tryParse(json['timestamp']) + timestamp: timestamp != null + ? DateTime.tryParse(timestamp) : null, message: json['message'], category: json['category'], - data: json['data'] as Map?, + data: json['data'], level: levelName != null ? SentryLevel.fromName(levelName) : null, type: json['type'], ); diff --git a/dart/lib/src/protocol/debug_meta.dart b/dart/lib/src/protocol/debug_meta.dart index f80ce5a44b..6585fb699c 100644 --- a/dart/lib/src/protocol/debug_meta.dart +++ b/dart/lib/src/protocol/debug_meta.dart @@ -24,12 +24,10 @@ class DebugMeta { final debugImagesJson = json['images'] as List?; return DebugMeta( sdk: sdkInfoJson != null ? SdkInfo.fromJson(sdkInfoJson) : null, - images: debugImagesJson != null - ? debugImagesJson - .map((debugImageJson) => - DebugImage.fromJson(debugImageJson as Map)) - .toList() - : null); + images: debugImagesJson?.map((debugImageJson) => + DebugImage.fromJson(debugImageJson as Map) + ).toList(), + ); } /// Produces a [Map] that can be serialized to JSON. diff --git a/dart/lib/src/protocol/sdk_version.dart b/dart/lib/src/protocol/sdk_version.dart index 37355d7613..50910b7e43 100644 --- a/dart/lib/src/protocol/sdk_version.dart +++ b/dart/lib/src/protocol/sdk_version.dart @@ -73,7 +73,8 @@ class SdkVersion { packages: packagesJson ?.map((e) => SentryPackage.fromJson(e as Map)) .toList(), - integrations: integrationsJson?.map((e) => e as String).toList()); + integrations: integrationsJson?.map((e) => e as String).toList(), + ); } /// Produces a [Map] that can be serialized to JSON. diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 389cc0868a..8c23ab6dbf 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -228,7 +228,7 @@ class SentryEvent { /// Deserializes a [SentryEvent] from JSON [Map]. factory SentryEvent.fromJson(Map json) { - final breadcrumbsJson = json['breadcrumbs'] as List?; + final breadcrumbsJson = json['breadcrumbs']; final breadcrumbs = breadcrumbsJson?.map((e) { return Breadcrumb.fromJson(e); }).toList(); @@ -248,24 +248,22 @@ class SentryEvent { exceptionValuesItemJson = exceptionValuesJson?.first; } - final modulesJson = json['modules'] as Map?; + final modulesJson = json['modules']; Map? modules; if (modulesJson != null) { modules = {}; - modulesJson.forEach((key, value) { - modules?[key] = value; - }); + modules.addAll(modulesJson); } - final tagsJson = json['tags'] as Map?; + final tagsJson = json['tags']; Map? tags; if (tagsJson != null) { tags = {}; - tagsJson.forEach((key, value) { - tags?[key] = value; - }); + tags.addAll(tagsJson); } + final timestampJson = json['timestamp']; + final levelJson = json['level']; final fingerprintJson = json['fingerprint'] as List?; final sdkVersionJson = json['sdk'] as Map?; final messageJson = json['message'] as Map?; @@ -276,9 +274,8 @@ class SentryEvent { return SentryEvent( eventId: SentryId.fromId(json['event_id']), - timestamp: json['timestamp'] != null - ? DateTime.tryParse(json['timestamp']) - : null, + timestamp: + timestampJson != null ? DateTime.tryParse(timestampJson) : null, modules: modules, tags: tags, extra: json['extra'], @@ -305,7 +302,7 @@ class SentryEvent { exceptionValuesItemJson != null && exceptionValuesItemJson.isNotEmpty ? SentryException.fromJson(exceptionValuesItemJson) : null, - level: json['level'] != null ? SentryLevel.fromName(json['level']) : null, + level: levelJson != null ? SentryLevel.fromName(levelJson) : null, culprit: json['culprit'], user: userJson != null && userJson.isNotEmpty ? SentryUser.fromJson(userJson) diff --git a/dart/lib/src/protocol/sentry_exception.dart b/dart/lib/src/protocol/sentry_exception.dart index 3297713db3..a8f5f5a004 100644 --- a/dart/lib/src/protocol/sentry_exception.dart +++ b/dart/lib/src/protocol/sentry_exception.dart @@ -34,17 +34,20 @@ class SentryException { /// Deserializes a [SentryException] from JSON [Map]. factory SentryException.fromJson(Map json) { + final stackTraceJson = json['stacktrace']; + final mechanismJson = json['mechanism']; return SentryException( type: json['type'], value: json['value'], module: json['module'], - stackTrace: json['stacktrace'] != null - ? SentryStackTrace.fromJson(json['stacktrace']) + stackTrace: stackTraceJson != null + ? SentryStackTrace.fromJson(stackTraceJson) : null, - mechanism: json['mechanism'] != null - ? Mechanism.fromJson(json['mechanism']) + mechanism: mechanismJson != null + ? Mechanism.fromJson(mechanismJson) : null, - threadId: json['thread_id']); + threadId: json['thread_id'], + ); } /// Produces a [Map] that can be serialized to JSON. diff --git a/dart/lib/src/protocol/sentry_message.dart b/dart/lib/src/protocol/sentry_message.dart index 2c2a4176b0..e234de5584 100644 --- a/dart/lib/src/protocol/sentry_message.dart +++ b/dart/lib/src/protocol/sentry_message.dart @@ -24,8 +24,11 @@ class SentryMessage { /// Deserializes a [SentryMessage] from JSON [Map]. factory SentryMessage.fromJson(Map json) { - return SentryMessage(json['formatted'], - template: json['message'], params: json['params']); + return SentryMessage( + json['formatted'], + template: json['message'], + params: json['params'], + ); } /// Produces a [Map] that can be serialized to JSON. diff --git a/dart/lib/src/protocol/sentry_stack_trace.dart b/dart/lib/src/protocol/sentry_stack_trace.dart index 2330f7af03..b593e0d31e 100644 --- a/dart/lib/src/protocol/sentry_stack_trace.dart +++ b/dart/lib/src/protocol/sentry_stack_trace.dart @@ -34,7 +34,8 @@ class SentryStackTrace { .map((frameJson) => SentryStackFrame.fromJson(frameJson)) .toList() : [], - registers: json['registers'] as Map?); + registers: json['registers'], + ); } /// Produces a [Map] that can be serialized to JSON. diff --git a/dart/test/sentry_event_test.dart b/dart/test/sentry_event_test.dart index 35e0b4ba3f..1a89f1f1ff 100644 --- a/dart/test/sentry_event_test.dart +++ b/dart/test/sentry_event_test.dart @@ -60,6 +60,14 @@ void main() { }, }; + final emptyFieldsSentryEventJson = { + 'event_id': sentryId.toString(), + 'timestamp': formatDateAsIso8601WithMillisPrecision(timestamp), + 'contexts': { + 'device': {'name': 'name'} + }, + }; + test('fromJson', () { final sentryEvent = SentryEvent.fromJson(sentryEventJson); final json = sentryEvent.toJson(); @@ -69,6 +77,32 @@ void main() { true, ); }); + + test('should not deserialize null or empty fields', () { + final sentryEvent = SentryEvent.fromJson(emptyFieldsSentryEventJson); + + expect(sentryEvent.platform, isNull); + expect(sentryEvent.logger, isNull); + expect(sentryEvent.serverName, isNull); + expect(sentryEvent.release, isNull); + expect(sentryEvent.dist, isNull); + expect(sentryEvent.environment, isNull); + expect(sentryEvent.modules, isNull); + expect(sentryEvent.message, isNull); + expect(sentryEvent.stackTrace, isNull); + expect(sentryEvent.exception, isNull); + expect(sentryEvent.transaction, isNull); + expect(sentryEvent.level, isNull); + expect(sentryEvent.culprit, isNull); + expect(sentryEvent.tags, isNull); + expect(sentryEvent.extra, isNull); + expect(sentryEvent.breadcrumbs, isNull); + expect(sentryEvent.user, isNull); + expect(sentryEvent.fingerprint, isNull); + expect(sentryEvent.sdk, isNull); + expect(sentryEvent.request, isNull); + expect(sentryEvent.debugMeta, isNull); + }); }); group(SentryEvent, () { From 49f0a5974290bff1e314f272a2fd153671c32459 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 13:32:55 +0200 Subject: [PATCH 33/48] Remove unused comment --- dart/test/sentry_client_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 950e33f75e..9b6bd5dc65 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -248,7 +248,6 @@ void main() { (options.transport as MockTransport).envelopes.first; final capturedEvent = await eventFromEnvelope(capturedEnvelope); - //expect(capturedEvent.throwable, exception); // Cannot recreate insance from envelope... expect(capturedEvent.exception is SentryException, true); expect(capturedEvent.exception!.stackTrace!.frames.first.fileName, 'test.dart'); From 32c6a71927b613794cf7e1aff9e6de1ef80e645c Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 13:41:26 +0200 Subject: [PATCH 34/48] Assert stacktrace info --- dart/test/sentry_client_test.dart | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 9b6bd5dc65..f8b516a132 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -152,7 +152,11 @@ void main() { var options = SentryOptions(dsn: fakeDsn); Error error; - StackTrace stackTrace; + final stackTrace = ''' +#0 baz (file:///pathto/test.dart:50:3) + +#1 bar (file:///pathto/test.dart:46:9) + '''; setUp(() { options = SentryOptions(dsn: fakeDsn); @@ -160,11 +164,11 @@ void main() { }); test('should capture error', () async { + try { throw StateError('Error'); - } on Error catch (err, stack) { + } on Error catch (err) { error = err; - stackTrace = stack; } final client = SentryClient(options); @@ -176,6 +180,8 @@ void main() { expect(capturedEvent.exception is SentryException, true); expect(capturedEvent.exception!.stackTrace, isNotNull); + expect(capturedEvent.exception!.stackTrace!.frames.first.lineNo, 46); + expect(capturedEvent.exception!.stackTrace!.frames.first.colNo, 9); }); }); From e38c1cb04a44c5f1689e85deacf69d853320532e Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 13:50:03 +0200 Subject: [PATCH 35/48] Restore type casts --- dart/lib/src/protocol/sentry_event.dart | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 8c23ab6dbf..55f4de71f3 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -228,7 +228,7 @@ class SentryEvent { /// Deserializes a [SentryEvent] from JSON [Map]. factory SentryEvent.fromJson(Map json) { - final breadcrumbsJson = json['breadcrumbs']; + final breadcrumbsJson = json['breadcrumbs'] as List?; final breadcrumbs = breadcrumbsJson?.map((e) { return Breadcrumb.fromJson(e); }).toList(); @@ -248,18 +248,22 @@ class SentryEvent { exceptionValuesItemJson = exceptionValuesJson?.first; } - final modulesJson = json['modules']; + final modulesJson = json['modules'] as Map?; Map? modules; if (modulesJson != null) { modules = {}; - modules.addAll(modulesJson); + modulesJson.forEach((key, value) { + modules?[key] = value; + }); } - final tagsJson = json['tags']; + final tagsJson = json['tags'] as Map?; Map? tags; if (tagsJson != null) { tags = {}; - tags.addAll(tagsJson); + tagsJson.forEach((key, value) { + tags?[key] = value; + }); } final timestampJson = json['timestamp']; From 3a6b87d08b095e9f4400f498efed166ee4726d80 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 14:00:39 +0200 Subject: [PATCH 36/48] Update formating --- dart/lib/src/protocol/breadcrumb.dart | 4 +--- dart/lib/src/protocol/debug_meta.dart | 11 +++++----- dart/lib/src/protocol/sdk_version.dart | 14 ++++++------- dart/lib/src/protocol/sentry_exception.dart | 21 +++++++++---------- dart/lib/src/protocol/sentry_stack_trace.dart | 14 ++++++------- dart/test/sentry_client_test.dart | 1 - dart/test/sentry_event_test.dart | 2 +- 7 files changed, 32 insertions(+), 35 deletions(-) diff --git a/dart/lib/src/protocol/breadcrumb.dart b/dart/lib/src/protocol/breadcrumb.dart index 7259d58121..10c60e684b 100644 --- a/dart/lib/src/protocol/breadcrumb.dart +++ b/dart/lib/src/protocol/breadcrumb.dart @@ -81,9 +81,7 @@ class Breadcrumb { final levelName = json['level']; final timestamp = json['timestamp']; return Breadcrumb( - timestamp: timestamp != null - ? DateTime.tryParse(timestamp) - : null, + timestamp: timestamp != null ? DateTime.tryParse(timestamp) : null, message: json['message'], category: json['category'], data: json['data'], diff --git a/dart/lib/src/protocol/debug_meta.dart b/dart/lib/src/protocol/debug_meta.dart index 6585fb699c..24d8183d54 100644 --- a/dart/lib/src/protocol/debug_meta.dart +++ b/dart/lib/src/protocol/debug_meta.dart @@ -23,11 +23,12 @@ class DebugMeta { final sdkInfoJson = json['sdk_info']; final debugImagesJson = json['images'] as List?; return DebugMeta( - sdk: sdkInfoJson != null ? SdkInfo.fromJson(sdkInfoJson) : null, - images: debugImagesJson?.map((debugImageJson) => - DebugImage.fromJson(debugImageJson as Map) - ).toList(), - ); + sdk: sdkInfoJson != null ? SdkInfo.fromJson(sdkInfoJson) : null, + images: debugImagesJson + ?.map((debugImageJson) => + DebugImage.fromJson(debugImageJson as Map)) + .toList(), + ); } /// Produces a [Map] that can be serialized to JSON. diff --git a/dart/lib/src/protocol/sdk_version.dart b/dart/lib/src/protocol/sdk_version.dart index 50910b7e43..b69ca3c130 100644 --- a/dart/lib/src/protocol/sdk_version.dart +++ b/dart/lib/src/protocol/sdk_version.dart @@ -68,13 +68,13 @@ class SdkVersion { final packagesJson = json['packages'] as List?; final integrationsJson = json['integrations'] as List?; return SdkVersion( - name: json['name'], - version: json['version'], - packages: packagesJson - ?.map((e) => SentryPackage.fromJson(e as Map)) - .toList(), - integrations: integrationsJson?.map((e) => e as String).toList(), - ); + name: json['name'], + version: json['version'], + packages: packagesJson + ?.map((e) => SentryPackage.fromJson(e as Map)) + .toList(), + integrations: integrationsJson?.map((e) => e as String).toList(), + ); } /// Produces a [Map] that can be serialized to JSON. diff --git a/dart/lib/src/protocol/sentry_exception.dart b/dart/lib/src/protocol/sentry_exception.dart index a8f5f5a004..8359bfd1a3 100644 --- a/dart/lib/src/protocol/sentry_exception.dart +++ b/dart/lib/src/protocol/sentry_exception.dart @@ -37,17 +37,16 @@ class SentryException { final stackTraceJson = json['stacktrace']; final mechanismJson = json['mechanism']; return SentryException( - type: json['type'], - value: json['value'], - module: json['module'], - stackTrace: stackTraceJson != null - ? SentryStackTrace.fromJson(stackTraceJson) - : null, - mechanism: mechanismJson != null - ? Mechanism.fromJson(mechanismJson) - : null, - threadId: json['thread_id'], - ); + type: json['type'], + value: json['value'], + module: json['module'], + stackTrace: stackTraceJson != null + ? SentryStackTrace.fromJson(stackTraceJson) + : null, + mechanism: + mechanismJson != null ? Mechanism.fromJson(mechanismJson) : null, + threadId: json['thread_id'], + ); } /// Produces a [Map] that can be serialized to JSON. diff --git a/dart/lib/src/protocol/sentry_stack_trace.dart b/dart/lib/src/protocol/sentry_stack_trace.dart index b593e0d31e..abb74fdcca 100644 --- a/dart/lib/src/protocol/sentry_stack_trace.dart +++ b/dart/lib/src/protocol/sentry_stack_trace.dart @@ -29,13 +29,13 @@ class SentryStackTrace { factory SentryStackTrace.fromJson(Map json) { final framesJson = json['frames'] as List?; return SentryStackTrace( - frames: framesJson != null - ? framesJson - .map((frameJson) => SentryStackFrame.fromJson(frameJson)) - .toList() - : [], - registers: json['registers'], - ); + frames: framesJson != null + ? framesJson + .map((frameJson) => SentryStackFrame.fromJson(frameJson)) + .toList() + : [], + registers: json['registers'], + ); } /// Produces a [Map] that can be serialized to JSON. diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index f8b516a132..b6762ccb5a 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -164,7 +164,6 @@ void main() { }); test('should capture error', () async { - try { throw StateError('Error'); } on Error catch (err) { diff --git a/dart/test/sentry_event_test.dart b/dart/test/sentry_event_test.dart index 1a89f1f1ff..17ec510175 100644 --- a/dart/test/sentry_event_test.dart +++ b/dart/test/sentry_event_test.dart @@ -79,7 +79,7 @@ void main() { }); test('should not deserialize null or empty fields', () { - final sentryEvent = SentryEvent.fromJson(emptyFieldsSentryEventJson); + final sentryEvent = SentryEvent.fromJson(emptyFieldsSentryEventJson); expect(sentryEvent.platform, isNull); expect(sentryEvent.logger, isNull); From 9eb61c78ff064a1e97efe4fc0a6867d8af240bb6 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 15:19:15 +0200 Subject: [PATCH 37/48] Dry extraction of Map --- dart/lib/src/protocol/sentry_event.dart | 26 +++++++++---------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 55f4de71f3..56aa178c62 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -248,23 +248,8 @@ class SentryEvent { exceptionValuesItemJson = exceptionValuesJson?.first; } - final modulesJson = json['modules'] as Map?; - Map? modules; - if (modulesJson != null) { - modules = {}; - modulesJson.forEach((key, value) { - modules?[key] = value; - }); - } - - final tagsJson = json['tags'] as Map?; - Map? tags; - if (tagsJson != null) { - tags = {}; - tagsJson.forEach((key, value) { - tags?[key] = value; - }); - } + final modules = _stringKeyValues('modules', json); + final tags = _stringKeyValues('tags', json); final timestampJson = json['timestamp']; final levelJson = json['level']; @@ -439,4 +424,11 @@ class SentryEvent { return json; } + + static Map? _stringKeyValues( + String key, Map json) { + Map? mapDynamicValues = json[key]; + return mapDynamicValues + ?.map((key, value) => MapEntry(key, value as String)); + } } From b031c51d0e2c2076b7f98e074add95f2da32f3b3 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 15:24:29 +0200 Subject: [PATCH 38/48] Use dart:core cast --- dart/lib/src/protocol/sentry_event.dart | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 56aa178c62..4b6f9d7460 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -248,9 +248,9 @@ class SentryEvent { exceptionValuesItemJson = exceptionValuesJson?.first; } - final modules = _stringKeyValues('modules', json); - final tags = _stringKeyValues('tags', json); - + final modules = json['modules']?.cast(); + final tags = json['tags']?.cast(); + final timestampJson = json['timestamp']; final levelJson = json['level']; final fingerprintJson = json['fingerprint'] as List?; @@ -424,11 +424,4 @@ class SentryEvent { return json; } - - static Map? _stringKeyValues( - String key, Map json) { - Map? mapDynamicValues = json[key]; - return mapDynamicValues - ?.map((key, value) => MapEntry(key, value as String)); - } } From b21bfeb71aad3e0488d1cfc0ea961136bc224e00 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 26 Apr 2021 15:50:44 +0200 Subject: [PATCH 39/48] Format sentry event --- dart/lib/src/protocol/sentry_event.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index 4b6f9d7460..c7bf163415 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -250,7 +250,7 @@ class SentryEvent { final modules = json['modules']?.cast(); final tags = json['tags']?.cast(); - + final timestampJson = json['timestamp']; final levelJson = json['level']; final fingerprintJson = json['fingerprint'] as List?; From 348bb15b078320223aeded6c39e44c0cd36c7986 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 17 May 2021 11:06:55 +0200 Subject: [PATCH 40/48] format --- dart/lib/src/protocol/sentry_device.dart | 70 ++++++++++++------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/dart/lib/src/protocol/sentry_device.dart b/dart/lib/src/protocol/sentry_device.dart index e818da71a2..7476002994 100644 --- a/dart/lib/src/protocol/sentry_device.dart +++ b/dart/lib/src/protocol/sentry_device.dart @@ -134,41 +134,41 @@ class SentryDevice { /// Deserializes a [SentryDevice] from JSON [Map]. factory SentryDevice.fromJson(Map data) => SentryDevice( - name: data['name'], - family: data['family'], - model: data['model'], - modelId: data['model_id'], - arch: data['arch'], - batteryLevel: data['battery_level'], - orientation: data['orientation'] == 'portrait' - ? SentryOrientation.portrait - : data['orientation'] == 'landscape' - ? SentryOrientation.landscape - : null, - manufacturer: data['manufacturer'], - brand: data['brand'], - screenResolution: data['screen_resolution'], - screenHeightPixels: data['screen_height_pixels'], - screenWidthPixels: data['screen_width_pixels'], - screenDensity: data['screen_density'], - screenDpi: data['screen_dpi'], - online: data['online'], - charging: data['charging'], - lowMemory: data['low_memory'], - simulator: data['simulator'], - memorySize: data['memory_size'], - freeMemory: data['free_memory'], - usableMemory: data['usable_memory'], - storageSize: data['storage_size'], - freeStorage: data['free_storage'], - externalStorageSize: data['external_storage_size'], - externalFreeStorage: data['external_free_storage'], - bootTime: data['boot_time'] != null - ? DateTime.tryParse(data['boot_time']) - : null, - timezone: data['timezone'], - language: data['language'], - ); + name: data['name'], + family: data['family'], + model: data['model'], + modelId: data['model_id'], + arch: data['arch'], + batteryLevel: data['battery_level'], + orientation: data['orientation'] == 'portrait' + ? SentryOrientation.portrait + : data['orientation'] == 'landscape' + ? SentryOrientation.landscape + : null, + manufacturer: data['manufacturer'], + brand: data['brand'], + screenResolution: data['screen_resolution'], + screenHeightPixels: data['screen_height_pixels'], + screenWidthPixels: data['screen_width_pixels'], + screenDensity: data['screen_density'], + screenDpi: data['screen_dpi'], + online: data['online'], + charging: data['charging'], + lowMemory: data['low_memory'], + simulator: data['simulator'], + memorySize: data['memory_size'], + freeMemory: data['free_memory'], + usableMemory: data['usable_memory'], + storageSize: data['storage_size'], + freeStorage: data['free_storage'], + externalStorageSize: data['external_storage_size'], + externalFreeStorage: data['external_free_storage'], + bootTime: data['boot_time'] != null + ? DateTime.tryParse(data['boot_time']) + : null, + timezone: data['timezone'], + language: data['language'], + ); /// Produces a [Map] that can be serialized to JSON. Map toJson() { From 8519169844860ff2057c85f4bd2b56bb19f5e605 Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 17 May 2021 18:49:37 +0200 Subject: [PATCH 41/48] Add missing properties to clone method --- dart/lib/src/protocol/sentry_device.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dart/lib/src/protocol/sentry_device.dart b/dart/lib/src/protocol/sentry_device.dart index 7476002994..785410a1c5 100644 --- a/dart/lib/src/protocol/sentry_device.dart +++ b/dart/lib/src/protocol/sentry_device.dart @@ -314,6 +314,8 @@ class SentryDevice { manufacturer: manufacturer, brand: brand, screenResolution: screenResolution, + screenHeightPixels: screenHeightPixels, + screenWidthPixels: screenWidthPixels, screenDensity: screenDensity, screenDpi: screenDpi, online: online, @@ -328,7 +330,8 @@ class SentryDevice { externalStorageSize: externalStorageSize, externalFreeStorage: externalFreeStorage, bootTime: bootTime, - timezone: timezone, // TODO(denrase) Language not cloned? + timezone: timezone, + language: language ); SentryDevice copyWith({ From a2b52441c415a512f48144a365f4bb0b6b3031cb Mon Sep 17 00:00:00 2001 From: denrase Date: Mon, 17 May 2021 18:55:07 +0200 Subject: [PATCH 42/48] format --- dart/lib/src/protocol/sentry_device.dart | 57 ++++++++++++------------ 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/dart/lib/src/protocol/sentry_device.dart b/dart/lib/src/protocol/sentry_device.dart index 785410a1c5..2630b8d6c1 100644 --- a/dart/lib/src/protocol/sentry_device.dart +++ b/dart/lib/src/protocol/sentry_device.dart @@ -304,35 +304,34 @@ class SentryDevice { } SentryDevice clone() => SentryDevice( - name: name, - family: family, - model: model, - modelId: modelId, - arch: arch, - batteryLevel: batteryLevel, - orientation: orientation, - manufacturer: manufacturer, - brand: brand, - screenResolution: screenResolution, - screenHeightPixels: screenHeightPixels, - screenWidthPixels: screenWidthPixels, - screenDensity: screenDensity, - screenDpi: screenDpi, - online: online, - charging: charging, - lowMemory: lowMemory, - simulator: simulator, - memorySize: memorySize, - freeMemory: freeMemory, - usableMemory: usableMemory, - storageSize: storageSize, - freeStorage: freeStorage, - externalStorageSize: externalStorageSize, - externalFreeStorage: externalFreeStorage, - bootTime: bootTime, - timezone: timezone, - language: language - ); + name: name, + family: family, + model: model, + modelId: modelId, + arch: arch, + batteryLevel: batteryLevel, + orientation: orientation, + manufacturer: manufacturer, + brand: brand, + screenResolution: screenResolution, + screenHeightPixels: screenHeightPixels, + screenWidthPixels: screenWidthPixels, + screenDensity: screenDensity, + screenDpi: screenDpi, + online: online, + charging: charging, + lowMemory: lowMemory, + simulator: simulator, + memorySize: memorySize, + freeMemory: freeMemory, + usableMemory: usableMemory, + storageSize: storageSize, + freeStorage: freeStorage, + externalStorageSize: externalStorageSize, + externalFreeStorage: externalFreeStorage, + bootTime: bootTime, + timezone: timezone, + language: language); SentryDevice copyWith({ String? name, From aac65abc5c4a96eda4339729be8d46984573579d Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 18 May 2021 15:11:24 +0200 Subject: [PATCH 43/48] Send bytes over bridge and implement android side --- dart/lib/src/sentry_envelope.dart | 2 +- dart/lib/src/sentry_envelope_item.dart | 4 ++-- dart/lib/src/sentry_envelope_item_header.dart | 3 +++ .../main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt | 8 ++++---- flutter/lib/src/file_system_transport.dart | 8 +++----- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/dart/lib/src/sentry_envelope.dart b/dart/lib/src/sentry_envelope.dart index bf775df479..18a1835231 100644 --- a/dart/lib/src/sentry_envelope.dart +++ b/dart/lib/src/sentry_envelope.dart @@ -21,7 +21,7 @@ class SentryEnvelope { [SentryEnvelopeItem.fromEvent(event)]); } - /// Stream binary data representation of `Envelope` file encoded in utf8. + /// Stream binary data representation of `Envelope` file encoded. Stream> envelopeStream() async* { yield utf8.encode(jsonEncode(header.toJson())); final newLineData = utf8.encode('\n'); diff --git a/dart/lib/src/sentry_envelope_item.dart b/dart/lib/src/sentry_envelope_item.dart index 24930be25f..5c00a4e1e6 100644 --- a/dart/lib/src/sentry_envelope_item.dart +++ b/dart/lib/src/sentry_envelope_item.dart @@ -11,7 +11,7 @@ class SentryEnvelopeItem { /// Header with info about type and length of data in bytes. final SentryEnvelopeItemHeader header; - /// Create binary data representation of item JSON encoded in utf8. + /// Create binary data representation of item data. final Future> Function() dataFactory; /// Create an `SentryEnvelopeItem` which holds the `SentyEvent` data. @@ -31,7 +31,7 @@ class SentryEnvelopeItem { cachedItem.getData); } - /// Stream binary data of `Envelope` item encoded in utf8. + /// Stream binary data of `Envelope` item. Stream> envelopeItemStream() async* { yield utf8.encode(jsonEncode(await header.toJson())); yield utf8.encode('\n'); diff --git a/dart/lib/src/sentry_envelope_item_header.dart b/dart/lib/src/sentry_envelope_item_header.dart index 99a4580427..013a62d35b 100644 --- a/dart/lib/src/sentry_envelope_item_header.dart +++ b/dart/lib/src/sentry_envelope_item_header.dart @@ -19,6 +19,9 @@ class SentryEnvelopeItemHeader { if (contentType != null) { json['content_type'] = contentType; } + if (fileName != null) { + json['filename'] = fileName; + } json['type'] = type; json['length'] = await length(); return json; diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index 498ecfce22..8b6db22e6f 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -46,13 +46,13 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler { channel.setMethodCallHandler(null) } - private fun writeEnvelope(envelope: String): Boolean { + private fun writeEnvelope(envelope: ByteArray): Boolean { if (!this::options.isInitialized || options.outboxPath.isNullOrEmpty()) { return false } val file = File(options.outboxPath, UUID.randomUUID().toString()) - file.writeText(envelope, Charsets.UTF_8) + file.writeBytes(envelope) return true } @@ -124,9 +124,9 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler { private fun captureEnvelope(call: MethodCall, result: Result) { val args = call.arguments() as List if (args.isNotEmpty()) { - val event = args.first() as String? + val event = args.first() as ByteArray? - if (!event.isNullOrEmpty()) { + if (event != null && event.size > 0) { if (!writeEnvelope(event)) { result.error("3", "SentryOptions or outboxPath are null or empty", null) } diff --git a/flutter/lib/src/file_system_transport.dart b/flutter/lib/src/file_system_transport.dart index 844e2de383..68e47d3cde 100644 --- a/flutter/lib/src/file_system_transport.dart +++ b/flutter/lib/src/file_system_transport.dart @@ -1,4 +1,4 @@ -import 'dart:convert'; +import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:sentry/sentry.dart'; @@ -13,10 +13,8 @@ class FileSystemTransport implements Transport { Future send(SentryEnvelope envelope) async { final envelopeData = []; await envelope.envelopeStream().forEach(envelopeData.addAll); - - final envelopeString = utf8.decode(envelopeData); - - final args = [envelopeString]; + // https://flutter.dev/docs/development/platform-integration/platform-channels#codec + final args = [Uint8List.fromList(envelopeData)]; try { await _channel.invokeMethod('captureEnvelope', args); } catch (error) { From eeafe7577c955f38257a71cf38c3287f67222a92 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 18 May 2021 17:32:35 +0200 Subject: [PATCH 44/48] Deserialize envelope in native ios/macos bridge --- .../Classes/SentryFlutterPluginApple.swift | 61 ++---------------- flutter/ios/Classes/SentrySerialization.h | 15 +++++ flutter/macos/Classes/SentrySerialization.h | Bin 0 -> 1060 bytes 3 files changed, 22 insertions(+), 54 deletions(-) create mode 100644 flutter/ios/Classes/SentrySerialization.h create mode 100644 flutter/macos/Classes/SentrySerialization.h diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index f2aff5dfec..0ac20ad318 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -258,65 +258,18 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { private func captureEnvelope(_ call: FlutterMethodCall, result: @escaping FlutterResult) { guard let arguments = call.arguments as? [Any], !arguments.isEmpty, - let event = arguments.first as? String else { + let data = (arguments.first as? FlutterStandardTypedData)?.data else { print("Envelope is null or empty !") result(FlutterError(code: "2", message: "Envelope is null or empty", details: nil)) return } - do { - let envelope = try parseJsonEnvelope(event) - SentrySDK.capture(envelope) - result("") - } catch { - print("Cannot parse the envelope json !") - result(FlutterError(code: "3", message: "Cannot parse the envelope json", details: nil)) - return - } - } - - private func parseJsonEnvelope(_ data: String) throws -> SentryEnvelope { - let parts = data.split(separator: "\n") - - let envelopeParts: [[String: Any]] = try parts.map({ part in - guard let dict = parseJson(text: "\(part)") else { - throw NSError() - } - return dict - }) - - let rawEnvelopeHeader = envelopeParts[0] - guard let eventId = rawEnvelopeHeader["event_id"] as? String, - let itemType = envelopeParts[1]["type"] as? String else { - throw NSError() - } - - let sdkInfo = SentrySdkInfo(dict: rawEnvelopeHeader) - let sentryId = SentryId(uuidString: eventId) - let envelopeHeader = SentryEnvelopeHeader.init(id: sentryId, andSdkInfo: sdkInfo) - - let payload = envelopeParts[2] - - let data = try JSONSerialization.data(withJSONObject: payload, options: .init(rawValue: 0)) - - let itemHeader = SentryEnvelopeItemHeader(type: itemType, length: UInt(data.count)) - let sentryItem = SentryEnvelopeItem(header: itemHeader, data: data) - - return SentryEnvelope.init(header: envelopeHeader, singleItem: sentryItem) - } - - func parseJson(text: String) -> [String: Any]? { - guard let data = text.data(using: .utf8) else { - print("Invalid UTF8 String : \(text)") - return nil - } - - do { - let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] - return json - } catch { - print("json parsing error !") + guard let envelope = SentrySerialization.envelope(with: data) else { + print("Cannot parse the envelope data") + result(FlutterError(code: "3", message: "Cannot parse the envelope data", details: nil)) + return } - return nil + SentrySDK.capture(envelope) + result("") } } diff --git a/flutter/ios/Classes/SentrySerialization.h b/flutter/ios/Classes/SentrySerialization.h new file mode 100644 index 0000000000..3c7e3d29eb --- /dev/null +++ b/flutter/ios/Classes/SentrySerialization.h @@ -0,0 +1,15 @@ +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/* WARNING: This interface mirrors the cocoa SDK to access internal API. + * If signatures change in the cocoa sdk, this will break and we won't get a warning from the compiler. + */ +@interface SentrySerialization + ++ (SentryEnvelope *_Nullable)envelopeWithData:(NSData *)data; + +@end + +NS_ASSUME_NONNULL_END diff --git a/flutter/macos/Classes/SentrySerialization.h b/flutter/macos/Classes/SentrySerialization.h new file mode 100644 index 0000000000000000000000000000000000000000..5e502f6ccab7fa9653ec8d3adfdf15d73d90d300 GIT binary patch literal 1060 zcmZ9K&ui3B5XUENx2?5@-BzuKf>9KtH14*$Yr9gg`=i=}f>ePRD zeT&=d_;=o<{p|z(&jbFS=9xoWuX^7EZ$W>dLHvhNXdIe>u0XdT?w#+Wx-r)K<=vCZ z$Kh(YE2I)T0cKMpvxdt;NphDwPn|z$9=^)`lJzxowc>jAg?v6g$n}U{HJ4pK4kAaN zZ>V~Dr91pzJ3W2+)>ws~oCh^?wNhiUS~_n`P1edrsaUHRmFcO1Q7%+2O_YnJxq7j# z`hSEvl+gBYdgK`IpT{`CjPqH(y9DfiTj5#oOW_;fmhj>}z6t&;@h+X{vD`rh{9EE#aKFTJ;2Gf|@Tl-GcwATqJHiF9 oT3=fy+LSeOV5AZoTF2XwxYpX6p9S;%vW@)MegDj-z|Up<9r+P;{Qv*} literal 0 HcmV?d00001 From 0fbc8fcd752fc4044fcd644084650a3a7e1164b7 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 18 May 2021 17:42:34 +0200 Subject: [PATCH 45/48] Update test to native bridge --- flutter/test/file_system_transport_test.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/flutter/test/file_system_transport_test.dart b/flutter/test/file_system_transport_test.dart index f01612fd98..680deb073d 100644 --- a/flutter/test/file_system_transport_test.dart +++ b/flutter/test/file_system_transport_test.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -66,7 +67,8 @@ void main() { await transport.send(envelope); final envelopeList = arguments as List; - final envelopeString = envelopeList.first as String; + final envelopeData = envelopeList.first as Uint8List; + final envelopeString = utf8.decode(envelopeData); final lines = envelopeString.split('\n'); final envelopeHeader = lines.first; final itemHeader = lines[1]; From bffc2efff9100a8f54990cc09d9aa6fb508fcbd7 Mon Sep 17 00:00:00 2001 From: denrase Date: Tue, 18 May 2021 18:03:10 +0200 Subject: [PATCH 46/48] Add test for binary envelope --- dart/test/sentry_envelope_test.dart | 33 ++++++++++++++++++ .../envelope-with-image.envelope | Bin 0 -> 3712 bytes dart/test_resources/sentry.png | Bin 0 -> 3535 bytes 3 files changed, 33 insertions(+) create mode 100644 dart/test_resources/envelope-with-image.envelope create mode 100644 dart/test_resources/sentry.png diff --git a/dart/test/sentry_envelope_test.dart b/dart/test/sentry_envelope_test.dart index d04e0ee482..96846e1405 100644 --- a/dart/test/sentry_envelope_test.dart +++ b/dart/test/sentry_envelope_test.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'package:sentry/sentry.dart'; import 'package:sentry/src/sentry_envelope.dart'; @@ -70,5 +71,37 @@ void main() { expect(actualItem, expectedItem); }); + + test('item with binary payload', () async { + // Attachment + + final length = () async { + return 3535; + }; + final dataFactory = () async { + final file = File('test_resources/sentry.png'); + final bytes = await file.readAsBytes(); + return bytes; + }; + final attachmentHeader = SentryEnvelopeItemHeader('attachment', length, + contentType: 'image/png', fileName: 'sentry.png'); + final attachmentItem = SentryEnvelopeItem(attachmentHeader, dataFactory); + + // Envelope + + final eventId = SentryId.fromId('3b382f22ee67491f80f7dee18016a7b1'); + final sdkVersion = SdkVersion(name: 'test', version: 'version'); + final header = SentryEnvelopeHeader(eventId, sdkVersion); + final envelope = SentryEnvelope(header, [attachmentItem]); + + final envelopeData = []; + await envelope.envelopeStream().forEach(envelopeData.addAll); + + final expectedEnvelopeFile = + File('test_resources/envelope-with-image.envelope'); + final expectedEnvelopeData = await expectedEnvelopeFile.readAsBytes(); + + expect(expectedEnvelopeData, envelopeData); + }); }); } diff --git a/dart/test_resources/envelope-with-image.envelope b/dart/test_resources/envelope-with-image.envelope new file mode 100644 index 0000000000000000000000000000000000000000..533f5e4f6fc9c60af5fbb0311fdb5fdfc2e074e9 GIT binary patch literal 3712 zcmV-`4uA1`B4u`EZggL1WFk5uGh#D1GG;O|Wo0%uG&wP5I51{6WMySBI506bVK-ti zA}k_vWNRWidm?UOZDk@lB6MYQbRsMwc4cyNX>V>KIwE#ua&u{KZX$hs3VR}BZ*FvD zZggLCd2nSSIwEOpVP|D8aBgQJEFxxUY-Mg?ZDk@lB6DSKbaHtvaBgQJEFyGyaAhJo zB4KoNVPj}*Wo~pLEFx@WZfA68B04iQGc|n*iBL{Q4GJ0x0000DNk~Le0002t0002t z2m=5B010g(NB{r;hfqvZMgRZ*0002#>FMU?=5B6oL_|cdudn?4{Q3F$?Ck9I_4Ufi z%J1**_xJaHetwaWkx5BOzrVlV-`~y6&DPe|TwGi@I5<8&K4D>DxVX4xW@gjV(C;AvQ<@8V#tQV z000dGNklX+z>l6NQb-un3BCU1ku`I9_y?|Nr~m0TF?Es=7K!C*i(1A0=R~ zb*fHPcaDxabm-8bLx&C>I&}EILw__F44ZC5G7PUS^7+fd!|d+n^1R=4YpTcjO}2yS zKTWr&T3p>`0=MT)x2ifE-^l(gaXMAeb@0E? zMP&{5x|zlCkE?@+ zY){XeJ-lnWp+)iC*}*LP(sWY`!rj3v>owihLb$}f%wOrR7fm;|2#_g$433U|(Fcd< z+5Dsqu0Ht}KKa&gYYX6-W@`NzeROz?F@auuUw?K5pUoR>Z2?dxCYw)l`1DtUtu2BD z^x=NKsu+UNpdo+pn#uu6fO^L1cet~aH%x^S` z6KHNovA=`wd=Gr5IsAdvhRS9RiZQ6M;mp|-zSY*GDO3ezC&6#g(sq2U36RmSnBoIu zo=%guwg85tOSryCli0?pH<}8cQKXuw7A8$8)#N2M$`$`k+S(!@C)(?rV7|X?5;!r1 z-@&As4Udtk6SUC$wUq}Tfs?U_3G^r<-l{U2J}^a`y!!%OY*W&drXWsmp~{q5qSh7w z35c;JhdKO4dy=N)JZF=*g1me9iA7r^aIJhTZVIS&qb*5ODoR-4CPq{m(l4}wF^uxH zMU1(j%y=u3rag)&Hi+;{dZa|QfibvzZG$_1FiUyI79>qk58Q!&rIOCmf~4sHxndh` z)dlnaZ8$k}PXf(0CSG2n8jh!gE%)Quv^IZtlQZ#&jM0vy>Bv0Xl(|J-%8=)2o9@On ziPu~3ZN}alzS^3k>2HdFKH(Dxi7{RhH{6dg$!(wbST3xs|m+IW(rnWw5 zY9HnD_&2RDvpG>CjU^oV;sKP|nA7O+q$yK=mcH3B_=<-{)^M19a*^7WG^M@dZ!4+G zFKv^+iPk<4&PWhrw64tN*f^ONoJBlP)V`CZhNl|bi!Df+4jmax$_YEWI3@?M-ZGn~ z>}S}|xYixj&;Zfs)S5J1xmIC)VW2y4A(@cAS!dETU;W3|Fn#M+Mg*1ssmw3qikctB zMj<^7E>$($cnw4vG&Z%B+4N_h|MW3*f>-t70`<?ovfp{1%y;(>sHbl93s zn(mM8G@$ok<=PUqo6@Ia8}*dg$Q=?mPOo0AVACRH&TF{{g{I`jo<=+#vxLnV!i=kK^xi5$~5R#b#XQ>$hSr~-LUcLhW5aU3tig*0Q6}YgT2_l$O;e=?+zU zquTW7dSEKdtgy_6hJ5E-nwp+a^-ZD-OAJlS7$mRlHb+fQXqj6&8*3I^Bu$!UsTCp&d*;I5lfpdLm#Hbl{65q@dB*_@VT}r1# zR~nVm$XSd*LsCi7l0Fqp6jq!xWxKJ&)KK$KbI`04ID2OBj)tLdVJ4nJTI1H>A&hU8(vlvqk?BuY${6+= zMhuI9%&&L}U>?l|_lPlyO5lOl;22(S#6@#-(#cHK)9@88%pBRXXsEcPYbfo8Nwg2C zQ`l8JX?m}!OiSo)FO_U)5jiY7)BfW&FTohPJv9fL9CpQmz$DsPiK;JjAE17_hE7Ew zhHEq+*~KnKz{1Q@61ZAim>CO|3Plu?2Nun)L9G66f}SyrY9s{?*8aWhYXI*CZr`br zG1f5hziNFsP=;difW_^=7GD8UGHH6Om))z>FWnWzcLP@}kO9r19i_``)Rnr>+(OvD zO2efB6DXCfnlav?@`k!TewpD=faLAS@uBE^nC?RL)i|L?zNP&c#vONBG+7)z-cut zY{vLVhfV_AiIIlF(K0q-pHnW=U=QPyrdwljW*Tdho|P>iy;HW5a_xr`XVJIW?C|r2 zHQjVLP&21OljLiW#*axm$R0#4>dVy;KaKyR`D&c*8D5 z)O^ZXbdKcYhIN#6MI}u^E-}Oe`f0^m7C$`0a9sMPo@2iex7nZ!X^dhHkMky%_5hdZ zSj@GjmISl7{3zYi2!%FU?8V@=D3>x<;QS|0~Cv}b1Lh# zkT2v$^z{%Aitnx_lI%TX1e=_VgD~m*>*Cj(rH4Vrz$=P9#~Hv_+RSxv3DVu;=>K;ww6XAmwYkGpsbbz8BkqY6hMBnOuy`n`kFDMGJCtRUR3 z!sJF-1!+|lboy?7brOStl-zvo3KF7-5wM3tY{_>}_}`9l`N#4=LiI%#f>e-t%B z9#o8#7f_Z2?l9+dZ~MR_VeTF-oe%4*K~eaeY9DaLyL-6uD$Ezd6a$L!1$&6$ledTO zK}3Q{#OS1n9XhjeAzG%PpE*5R*q2N(0#Vd;DdpLve=GZ>g9EHYv_^cd~bKQjO zLGm7+Pfr1NOTl7sc4^h6-ak(#^B2dZ);5y!VL9|igX5Awov>Hzx6;4vp+kob9XfRA e(4j+z^!OjB9jyEhAyhE{0000E`C4~jn{Grh46iQo`OCw@?C$3Byx(+ds>k_Fwu9+EO}D68T-{~@x93f_syZCs$o?&H zI%>LQ72!Ac?=K#%n{Hbrcv3s~7yp5k+WTg8@W0SSWea}dYtt<(iPKOAv)iVdSPsv@ z4rbY9(~T^HV@C(G?6~P>mOyxoE-`JonZ@ystAmGZPtTk^ylc9lMe*I)!7TgIbW;n$ z-N7vDHQm-ixWvB9U+J$GO*gg(kSTr)j*foO2Z!j{{G<-9KKU0u`POi23*ee&YW*2~ zba;$0fnI!He|80*%^PiP0Z=C*m__@4;&I>&=fuHJVAluO+&3M0NQ4Yy=NZanX5)xTLihI_2=-+TO+M40Ah+i z;wh4-o*QUw5xha$rSyx8aTs|iG9pj#+yy-M6P{}wkSSP}d7n%l5iLLg2fp1LAZ#0S%Xl_Wczk~054}7ON{DIbn%4QCV zF{rWO%-Iya)z+jbR0U-x!Ee#hc6_Y~kkPQ1;sa!!PLsE`0EVPXxV}k~*v6_inhKv$ zq?)M~CQT{Th_NMyIs8U@lBVQ5XOp;synFbG zMO!3rt$ZzR3aECYElE=;VjFJN1@r%HI5~7r0?jriUS6Xbj;Dkz z_v6{LHh*`MGx3Rx(T=3)$UNMXxkX;ekmqTe?#4BV*IV#y#@-yh+M1;4Z;F6E;S&gn zFbHIZJ+q#vNu#_^BDeGUAQ-w>fGa|wmxZUALa7+H?1$TIZ-2xB^>(V0hHO8 z)9CP|DN}xyzS%MOiibwlaF~8_k=m9trM={DE2+ybZIi%>);JG12@jhtr=0M-z0wePSU#xjF4{)i{ca`WwIh^lL^ag#(^Z-5>`y5 zxZzgFKs=MM%*K+?Hn3`7IG8d^^lD9-YP`LNZ#s?lc^_Nu0y0LbGMn7j!)&6P$74De zWjiW0CQbbpTg~+rGu=EH{}#(^k|a&Hhuy8N2r>MXkZNbjN^Y@m*6 zMnyS%Awii9sR~nFE}W@d?4bZ>aU5E>>dR~(m#`R)^Wo9Md*dRD?%Ut7Z(S0(nn(>5iP9)udusGb*ZqG3Z~c1qJA;zdQ zX-ZpXQx|zc?Oj1#dB}>^vZK&zR%OzZmenWe4pn=j+VtppU@FY4u*`;reCJ%6nx0Vg zO`;4-3{A`!B(Lo@M@>&?nOiy=YZhE2O`4Lq+}GDNkLOm~EQaku3=<|z@wbIp&{Rg1 znQ5I`u`rd{RCG6ibA4#Us2Oz<-^>#v$r!_3N~c9v8kN(?S&TtLQc2R3>@*Xd(nT%* z-iK#R+E0`;MJG}*(@Gb$R?xb(YzN*=P`)sevUn=hDtl3DHmEkHqMamZN-XfEyGwWr zvU*gKc9x}2V3|!x2^<%OMO);K>FX4{K~vGDHBz!L6B99}$IHcDian(PH0Okz{8C9% zj*RU0-{4D0v|tW)mRb6QCr!&Rh9<9BI#3T)Uxk|KT$rg8R-80tyRpR7Q1ei8(5w?U zduH&ChM{m_CZ0lCH%@)-dwFYJE9ShGO!7#qGcrUjb4w zX?m=e-K*3u-4(@m16M4N0nMQurORy8mAcT}LfF4b!=(ZfD3z_6G2Wr_hPpoFpeR)r zuxA6dF-_7`wW%7HL&{2-MCn)rLL#gJEq~JV8mnP4-9?pVT`{MU^&bLlA*Z>5!pwmd z5^Gyg4hd@xpq+-w@)NxRWUO>i8$HP~%7rs>UxoZIOqy0uW;0UG_-b;HOw92(OXD~X zrFc`_O)w&fI8)!fA-P%cP9@)l>;@)Oswm7Hu({Ffsf-l4<6$~8FD#^ zPxzelYl7!vP)7Q?`OR1BcIwDR6~!!AYCe9BsMj^yNqb(D2QB~3vtF~kJ= zX~kO>KRm;5T>7S-W4{r%*`N$*jA9Ot^Cp+}0GH`l%(bVM1hcsODBbXA2|{E~6_OSq zJWsZ0flCB+Crv4VY{y%ml_+AhaI3jGLl|hi9DWP#SAbBu$mV@AHoS9WBhV(v)$BSF z>%7pNG~ZAm2WTZq^dfc`FMnaoeRUSlbh*^)=zo1Be< zFzNj3;@6y|he5``D~dhG8NgCI<6Dj<^Zm!13TW`8DOJh(%$N+&*!>n`_=4V&SQFk; zc!4q-O2;|xNr5OEn=a31qM;U?<<7Q{1pc|#N$zmobpt0$d0`3t79BjX>fIO85T9@4 z5)zi&g;ZWSUU&yMJJP0m+i{dbFV>@2?zIcjP;+`oEay99MBzKSPyQHh!6qRfqM%Va zr^pv_cChWj?E8qm;zwngc&Q2aj8`4E}%mzyc!h!1YN{b z#}co9C8~%#LoD41^s0rPf^ojMhc4=P8u(_v$Y+f#X^{@T8D7Ig<5Fvcm= zdBm2bNMnqFrQEL=H{^Q{xulv6q+y?fKNp+r?~6g=l_i8tbPV@dO|7_Mh~6wfhm4^3B7Ww7|`nz>+fN5CLyK)cWe0K zxDQ;KH{cfruD^o+2^~{^53kI_O@;A9t48XS@RE(7uP?iMlFz0n|`@kb%?jA0k z59_Q!QTUu{A8^IHd${r{%ooEH1B&qldx+taw}2-mm2)C0h4uGv%eAW7v1vyScdT&e^@WjWMGyDBXutL@ z7H#OE;885aD~jfOID_!!*gn=Ag~ogMtQ?Ya-GuBx@*bW~PXTvJ!D4ZCY1O6PKTjv~ z7ssX6Hj?vUIrK+^I&|pJp+krC_#dbpto#olR51Vm002ov JPDHLkV1hwO&o}@8 literal 0 HcmV?d00001 From 6f77ca01377f4bad104f991233f369766f9116dc Mon Sep 17 00:00:00 2001 From: denrase Date: Fri, 21 May 2021 09:48:12 +0200 Subject: [PATCH 47/48] Only run test with dart.io import on vm target, add changelog --- CHANGELOG.md | 2 + dart/test/sentry_envelope_header_test.dart | 2 +- dart/test/sentry_envelope_test.dart | 35 +--------------- dart/test/sentry_envelope_vm_test.dart | 46 ++++++++++++++++++++++ 4 files changed, 50 insertions(+), 35 deletions(-) create mode 100644 dart/test/sentry_envelope_vm_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index ccc2aebf73..6b6429d377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased +* Feature: Envelope Only Transport API #426 (#463) + # 5.1.0-beta.1 * Fix: `Sentry.close()` closes native SDK integrations (#388) diff --git a/dart/test/sentry_envelope_header_test.dart b/dart/test/sentry_envelope_header_test.dart index ae854489af..28f894e766 100644 --- a/dart/test/sentry_envelope_header_test.dart +++ b/dart/test/sentry_envelope_header_test.dart @@ -3,7 +3,7 @@ import 'package:sentry/src/sentry_envelope_header.dart'; import 'package:test/test.dart'; void main() { - group('SentryEnvelopeItemHeader', () { + group('SentryEnvelopeHeader', () { test('toJson empty', () { final sut = SentryEnvelopeHeader(null, null); final expected = {}; diff --git a/dart/test/sentry_envelope_test.dart b/dart/test/sentry_envelope_test.dart index 96846e1405..624e4b0992 100644 --- a/dart/test/sentry_envelope_test.dart +++ b/dart/test/sentry_envelope_test.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'dart:io'; import 'package:sentry/sentry.dart'; import 'package:sentry/src/sentry_envelope.dart'; @@ -11,7 +10,7 @@ import 'package:sentry/src/protocol/sentry_id.dart'; import 'package:test/test.dart'; void main() { - group('SentryEnvelopeItem', () { + group('SentryEnvelope', () { test('serialize', () async { final eventId = SentryId.newId(); @@ -71,37 +70,5 @@ void main() { expect(actualItem, expectedItem); }); - - test('item with binary payload', () async { - // Attachment - - final length = () async { - return 3535; - }; - final dataFactory = () async { - final file = File('test_resources/sentry.png'); - final bytes = await file.readAsBytes(); - return bytes; - }; - final attachmentHeader = SentryEnvelopeItemHeader('attachment', length, - contentType: 'image/png', fileName: 'sentry.png'); - final attachmentItem = SentryEnvelopeItem(attachmentHeader, dataFactory); - - // Envelope - - final eventId = SentryId.fromId('3b382f22ee67491f80f7dee18016a7b1'); - final sdkVersion = SdkVersion(name: 'test', version: 'version'); - final header = SentryEnvelopeHeader(eventId, sdkVersion); - final envelope = SentryEnvelope(header, [attachmentItem]); - - final envelopeData = []; - await envelope.envelopeStream().forEach(envelopeData.addAll); - - final expectedEnvelopeFile = - File('test_resources/envelope-with-image.envelope'); - final expectedEnvelopeData = await expectedEnvelopeFile.readAsBytes(); - - expect(expectedEnvelopeData, envelopeData); - }); }); } diff --git a/dart/test/sentry_envelope_vm_test.dart b/dart/test/sentry_envelope_vm_test.dart new file mode 100644 index 0000000000..ffbdd14e08 --- /dev/null +++ b/dart/test/sentry_envelope_vm_test.dart @@ -0,0 +1,46 @@ +@TestOn('vm') +import 'dart:io'; + +import 'package:sentry/sentry.dart'; +import 'package:sentry/src/sentry_envelope.dart'; +import 'package:sentry/src/sentry_envelope_header.dart'; +import 'package:sentry/src/sentry_envelope_item_header.dart'; +import 'package:sentry/src/sentry_envelope_item.dart'; +import 'package:sentry/src/protocol/sentry_id.dart'; +import 'package:test/test.dart'; + +void main() { + group('SentryEnvelopeItem', () { + test('item with binary payload', () async { + // Attachment + + final length = () async { + return 3535; + }; + final dataFactory = () async { + final file = File('test_resources/sentry.png'); + final bytes = await file.readAsBytes(); + return bytes; + }; + final attachmentHeader = SentryEnvelopeItemHeader('attachment', length, + contentType: 'image/png', fileName: 'sentry.png'); + final attachmentItem = SentryEnvelopeItem(attachmentHeader, dataFactory); + + // Envelope + + final eventId = SentryId.fromId('3b382f22ee67491f80f7dee18016a7b1'); + final sdkVersion = SdkVersion(name: 'test', version: 'version'); + final header = SentryEnvelopeHeader(eventId, sdkVersion); + final envelope = SentryEnvelope(header, [attachmentItem]); + + final envelopeData = []; + await envelope.envelopeStream().forEach(envelopeData.addAll); + + final expectedEnvelopeFile = + File('test_resources/envelope-with-image.envelope'); + final expectedEnvelopeData = await expectedEnvelopeFile.readAsBytes(); + + expect(expectedEnvelopeData, envelopeData); + }); + }); +} From b9b0127301194bf6bd9bdd60fa8542aa99ccad17 Mon Sep 17 00:00:00 2001 From: denrase Date: Fri, 21 May 2021 14:49:46 +0200 Subject: [PATCH 48/48] Use obj-c dynamism to access private api while we don't have public options --- .../ios/Classes/SentryFlutterPluginApple.swift | 9 ++++++--- flutter/ios/Classes/SentrySerialization.h | 15 --------------- flutter/macos/Classes/SentrySerialization.h | Bin 1060 -> 0 bytes 3 files changed, 6 insertions(+), 18 deletions(-) delete mode 100644 flutter/ios/Classes/SentrySerialization.h delete mode 100644 flutter/macos/Classes/SentrySerialization.h diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index 0ac20ad318..0a152db5dc 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -263,13 +263,16 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { result(FlutterError(code: "2", message: "Envelope is null or empty", details: nil)) return } - - guard let envelope = SentrySerialization.envelope(with: data) else { + // We need to replace this when we have the possibility to access envelope deserialization. + guard let sentrySerialization = NSClassFromString("SentrySerialization") as? NSObject.Type, + let unmanaged = sentrySerialization.perform(NSSelectorFromString("envelopeWithData:"), with: data), + let envelope = unmanaged.takeUnretainedValue() as? SentryEnvelope else { print("Cannot parse the envelope data") result(FlutterError(code: "3", message: "Cannot parse the envelope data", details: nil)) - return + return } SentrySDK.capture(envelope) result("") + return } } diff --git a/flutter/ios/Classes/SentrySerialization.h b/flutter/ios/Classes/SentrySerialization.h deleted file mode 100644 index 3c7e3d29eb..0000000000 --- a/flutter/ios/Classes/SentrySerialization.h +++ /dev/null @@ -1,15 +0,0 @@ -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -/* WARNING: This interface mirrors the cocoa SDK to access internal API. - * If signatures change in the cocoa sdk, this will break and we won't get a warning from the compiler. - */ -@interface SentrySerialization - -+ (SentryEnvelope *_Nullable)envelopeWithData:(NSData *)data; - -@end - -NS_ASSUME_NONNULL_END diff --git a/flutter/macos/Classes/SentrySerialization.h b/flutter/macos/Classes/SentrySerialization.h deleted file mode 100644 index 5e502f6ccab7fa9653ec8d3adfdf15d73d90d300..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1060 zcmZ9K&ui3B5XUENx2?5@-BzuKf>9KtH14*$Yr9gg`=i=}f>ePRD zeT&=d_;=o<{p|z(&jbFS=9xoWuX^7EZ$W>dLHvhNXdIe>u0XdT?w#+Wx-r)K<=vCZ z$Kh(YE2I)T0cKMpvxdt;NphDwPn|z$9=^)`lJzxowc>jAg?v6g$n}U{HJ4pK4kAaN zZ>V~Dr91pzJ3W2+)>ws~oCh^?wNhiUS~_n`P1edrsaUHRmFcO1Q7%+2O_YnJxq7j# z`hSEvl+gBYdgK`IpT{`CjPqH(y9DfiTj5#oOW_;fmhj>}z6t&;@h+X{vD`rh{9EE#aKFTJ;2Gf|@Tl-GcwATqJHiF9 oT3=fy+LSeOV5AZoTF2XwxYpX6p9S;%vW@)MegDj-z|Up<9r+P;{Qv*}