diff --git a/.github/actions/coverage/action.yml b/.github/actions/coverage/action.yml index 793488f143..d0167ffa2e 100644 --- a/.github/actions/coverage/action.yml +++ b/.github/actions/coverage/action.yml @@ -33,4 +33,4 @@ runs: with: path: './${{ inputs.directory }}/coverage/lcov.info' min_coverage: ${{ inputs.min-coverage }} - exclude: 'lib/src/native/cocoa/binding.dart' + exclude: 'lib/src/native/**/binding.dart lib/src/native/java/android_replay_recorder.dart' diff --git a/.github/file-filters.yml b/.github/file-filters.yml index 4da3356a47..7280ac9201 100644 --- a/.github/file-filters.yml +++ b/.github/file-filters.yml @@ -7,3 +7,4 @@ high_risk_code: &high_risk_code - "flutter/ios/Classes/SentryFlutterPluginApple.swift" - "flutter/lib/src/screenshot/recorder.dart" - "flutter/lib/src/screenshot/widget_filter.dart" + - "flutter/lib/src/native/java/android_replay_recorder.dart" diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index acd2650696..32eb5a3148 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -54,11 +54,6 @@ jobs: - run: dart doc --dry-run - - name: Run publish validation - run: | - dart pub get --directory ../scripts/publish_validation - dart run ../scripts/publish_validation/bin/publish_validation.dart --executable ${{ inputs.sdk }} - package-analysis: # `axel-op/dart-package-analyzer` is using `flutter pub upgrade` instead of `get`, # which ignores pubspec.yaml `dependency_overrides`. Because of that, all `release/*` branches are failing, diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index e5f7f676db..c007b1d4ee 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -32,13 +32,6 @@ jobs: matrix: os: [ubuntu] sdk: - - '2.18' - - '2.19' - - '3.0' - - '3.1' - - '3.2' - - '3.3' - - '3.4' - '3.5' - stable - beta diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 6190303bd2..737c81c15c 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -112,14 +112,17 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff # pin@v2.18.0 with: channel: main - - run: flutter upgrade + - run: flutter config --enable-swift-package-manager + - name: Run on iOS if: matrix.target == 'ios' run: flutter build ios --no-codesign + - name: Run on macOS if: matrix.target == 'macos' run: flutter build macos diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 5a1d087b27..2cf158b0f8 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -182,9 +182,6 @@ jobs: with: channel: ${{ matrix.sdk }} - - name: flutter upgrade - run: flutter upgrade - - name: flutter pub get run: flutter pub get @@ -204,10 +201,10 @@ jobs: # Start Xvfb with specific screen settings Xvfb -ac :99 -screen 0 1280x1024x16 & export DISPLAY=:99 - + # Start ChromeDriver chromedriver --port=4444 & - + # Wait for services to start sleep 5 @@ -215,4 +212,4 @@ jobs: flutter drive \ --driver=integration_test/test_driver/driver.dart \ --target=integration_test/web_sdk_test.dart \ - -d chrome \ No newline at end of file + -d chrome diff --git a/.github/workflows/min_version_test.yml b/.github/workflows/min_version_test.yml index f3af7cec32..f96746121b 100644 --- a/.github/workflows/min_version_test.yml +++ b/.github/workflows/min_version_test.yml @@ -32,11 +32,11 @@ jobs: - uses: actions/setup-java@v4 with: distribution: "adopt" - java-version: "11" + java-version: "17" - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff # pin@v2.18.0 with: - flutter-version: "3.0.0" + flutter-version: "3.24.0" - name: Build Android run: | @@ -53,7 +53,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff # pin@v2.18.0 with: - flutter-version: "3.0.0" + flutter-version: "3.24.0" - uses: ruby/setup-ruby@277ba2a127aba66d45bad0fa2dc56f80dbfedffa # pin@v1.222.0 with: @@ -84,7 +84,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff # pin@v2.18.0 with: - flutter-version: "3.0.0" + flutter-version: "3.24.0" - name: Build web run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 050f7159d2..0dc95ae913 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,47 @@ # Changelog +## Unreleased 9.0.0 + +- Move replay and privacy from experimental to options ([#2755](https://github.com/getsentry/sentry-dart/pull/2755)) +- Remove renderer from `flutter_context` ([#2751](https://github.com/getsentry/sentry-dart/pull/2751)) +- Cleanup platform mocking ([#2730](https://github.com/getsentry/sentry-dart/pull/2730)) + - The `PlatformChecker` was renamed to `RuntimeChecker` + - Moved `PlatformChecker.platform` to `options.platform` + +## 9.0.0-alpha.1 + +### Breaking changes + +- Remove `SentryDisplayWidget` and manual TTID implementation ([#2668](https://github.com/getsentry/sentry-dart/pull/2668)) +- Increase minimum SDK version requirements to Dart v3.5.0 and Flutter v3.24.0 ([#2643](https://github.com/getsentry/sentry-dart/pull/2643)) +- Remove screenshot option `attachScreenshotOnlyWhenResumed` ([#2664](https://github.com/getsentry/sentry-dart/pull/2664)) +- Remove deprecated `beforeScreenshot` ([#2662](https://github.com/getsentry/sentry-dart/pull/2662)) +- Remove old user feedback api ([#2686](https://github.com/getsentry/sentry-dart/pull/2686)) +- Remove deprecated loggers ([#2685](https://github.com/getsentry/sentry-dart/pull/2685)) +- Remove user segment ([#2687](https://github.com/getsentry/sentry-dart/pull/2687)) +- Enable JS SDK native integration by default ([#2688](https://github.com/getsentry/sentry-dart/pull/2688)) +- Remove `enableTracing` ([#2695](https://github.com/getsentry/sentry-dart/pull/2695)) +- Remove `options.autoAppStart` and `setAppStartEnd` ([#2680](https://github.com/getsentry/sentry-dart/pull/2680)) +- Bump Drift min version to `2.24.0` and use `QueryInterceptor` instead of `QueryExecutor` ([#2679](https://github.com/getsentry/sentry-dart/pull/2679)) +- Add hint for transactions ([#2675](https://github.com/getsentry/sentry-dart/pull/2675)) + - `BeforeSendTransactionCallback` now has a `Hint` parameter +- Remove `dart:html` usage in favour of `package:web` ([#2710](https://github.com/getsentry/sentry-dart/pull/2710)) +- Remove max response body size ([#2709](https://github.com/getsentry/sentry-dart/pull/2709)) + - Responses are now only attached if size is below ~0.15mb + - Responses are attached to the `Hint` object, which can be read in `beforeSend`/`beforeSendTransaction` callbacks via `hint.response`. + - For now, only the `dio` integration is supported. +- Enable privacy masking for screenshots by default ([#2728](https://github.com/getsentry/sentry-dart/pull/2728)) + +### Enhancements + +- Replay: improve Android native interop performance by using JNI ([#2670](https://github.com/getsentry/sentry-dart/pull/2670)) + +### Dependencies + +- Bump Android SDK from v7.20.1 to v8.1.0 ([#2650](https://github.com/getsentry/sentry-dart/pull/2650)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#810) + - [diff](https://github.com/getsentry/sentry-java/compare/7.20.1...8.1.0) +## Unreleased ## 8.14.0 This release fixes an issue where Cold starts can be incorrectly reported as Warm starts on Android. @@ -97,6 +139,9 @@ final db = AppDatabase(executor); ### Dependencies +- Bump Android SDK from v7.20.1 to v8.2.0 ([#2660](https://github.com/getsentry/sentry-dart/pull/2660), [#2713](https://github.com/getsentry/sentry-dart/pull/2713)) + - [changelog](https://github.com/getsentry/sentry-java/blob/7.x.x/CHANGELOG.md#820) + - [diff](https://github.com/getsentry/sentry-java/compare/7.20.1...8.2.0) - Bump Native SDK from v0.7.19 to v0.7.20 ([#2652](https://github.com/getsentry/sentry-dart/pull/2652)) - [changelog](https://github.com/getsentry/sentry-native/blob/master/CHANGELOG.md#0720) - [diff](https://github.com/getsentry/sentry-native/compare/0.7.19...0.7.20) @@ -578,7 +623,6 @@ This release fixes an issue where Cold starts can be incorrectly reported as War ``` - Replace deprecated `BeforeScreenshotCallback` with new `BeforeCaptureCallback`. - ### Fixes - Catch errors thrown during `handleBeginFrame` and `handleDrawFrame` ([#2446](https://github.com/getsentry/sentry-dart/pull/2446)) diff --git a/dart/example/pubspec.yaml b/dart/example/pubspec.yaml index e344bbe25a..4851622d44 100644 --- a/dart/example/pubspec.yaml +++ b/dart/example/pubspec.yaml @@ -5,7 +5,7 @@ version: 1.0.0 publish_to: none environment: - sdk: '>=2.17.0 <4.0.0' + sdk: '>=3.5.0 <4.0.0' dependencies: sentry: diff --git a/dart/example_web/pubspec.yaml b/dart/example_web/pubspec.yaml index 141e5120ac..5001acbef0 100644 --- a/dart/example_web/pubspec.yaml +++ b/dart/example_web/pubspec.yaml @@ -4,12 +4,12 @@ description: An absolute bare-bones web app. publish_to: 'none' environment: - sdk: '>=2.17.0 <4.0.0' + sdk: '>=3.5.0 <4.0.0' dependencies: sentry: path: ../../dart/ - web: ^0.5.1 + web: ^1.1.0 dev_dependencies: build_runner: ^2.4.2 diff --git a/dart/example_web_legacy/.gitignore b/dart/example_web_legacy/.gitignore deleted file mode 100644 index 3d64647b50..0000000000 --- a/dart/example_web_legacy/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Files and directories created by pub -.dart_tool/ -.packages - -# Conventional directory for build outputs -build/ - -# Directory created by dartdoc -doc/api/ diff --git a/dart/example_web_legacy/README.md b/dart/example_web_legacy/README.md deleted file mode 100644 index 98202566f6..0000000000 --- a/dart/example_web_legacy/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Sentry Dart : web example - -```sh -dart pub get - -# run the project ( see https://dart.dev/tools/webdev#serve ) -dart run webdev serve --release -``` diff --git a/dart/example_web_legacy/analysis_options.yaml b/dart/example_web_legacy/analysis_options.yaml deleted file mode 100644 index be16ace7d1..0000000000 --- a/dart/example_web_legacy/analysis_options.yaml +++ /dev/null @@ -1,5 +0,0 @@ -include: package:lints/recommended.yaml - -analyzer: - errors: - path_does_not_exist: ignore diff --git a/dart/example_web_legacy/pubspec.yaml b/dart/example_web_legacy/pubspec.yaml deleted file mode 100644 index 49b7807084..0000000000 --- a/dart/example_web_legacy/pubspec.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: sentry_dart_web_example -description: An absolute bare-bones web app. - -publish_to: 'none' - -environment: - sdk: '>=2.17.0 <4.0.0' - -dependencies: - sentry: - path: ../../dart/ - -dev_dependencies: - build_runner: ^2.3.0 - build_web_compilers: ^3.2.3 - lints: ^2.0.0 - webdev: ^2.7.0 diff --git a/dart/example_web_legacy/web/event.dart b/dart/example_web_legacy/web/event.dart deleted file mode 100644 index 6e3e8b3e0b..0000000000 --- a/dart/example_web_legacy/web/event.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'package:sentry/src/protocol.dart'; - -final event = SentryEvent( - logger: 'main', - serverName: 'server.dart', - release: '1.4.0-preview.1', - environment: 'Test', - message: SentryMessage('This is an example Dart event.'), - tags: const {'project-id': '7371'}, - // ignore: deprecated_member_use, deprecated_member_use_from_same_package - extra: const {'section': '1'}, - // fingerprint: const ['example-dart'], - user: SentryUser( - id: '800', - username: 'first-user', - email: 'first@user.lan', - // ipAddress: '127.0.0.1', - data: {'first-sign-in': '2020-01-01'}, - ), - breadcrumbs: [ - Breadcrumb( - message: 'UI Lifecycle', - timestamp: DateTime.now().toUtc(), - category: 'ui.lifecycle', - type: 'navigation', - data: {'screen': 'MainActivity', 'state': 'created'}, - level: SentryLevel.info, - ) - ], - contexts: Contexts( - operatingSystem: const SentryOperatingSystem( - name: 'Android', - version: '5.0.2', - build: 'LRX22G.P900XXS0BPL2', - kernelVersion: - 'Linux version 3.4.39-5726670 (dpi@SWHC3807) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Dec 1 19:42:39 KST 2016', - rooted: false, - ), - runtimes: [const SentryRuntime(name: 'ART', version: '5')], - app: SentryApp( - name: 'Example Dart App', - version: '1.42.0', - identifier: 'HGT-App-13', - build: '93785', - buildType: 'release', - deviceAppHash: '5afd3a6', - startTime: DateTime.now().toUtc(), - ), - browser: const SentryBrowser(name: 'Firefox', version: '42.0.1'), - device: SentryDevice( - name: 'SM-P900', - family: 'SM-P900', - model: 'SM-P900 (LRX22G)', - modelId: 'LRX22G', - arch: 'armeabi-v7a', - batteryLevel: 99, - orientation: SentryOrientation.landscape, - manufacturer: 'samsung', - brand: 'samsung', - screenDensity: 2.1, - screenDpi: 320, - online: true, - charging: true, - lowMemory: true, - simulator: false, - memorySize: 1500, - freeMemory: 200, - usableMemory: 4294967296, - storageSize: 4294967296, - freeStorage: 2147483648, - externalStorageSize: 8589934592, - externalFreeStorage: 2863311530, - bootTime: DateTime.now().toUtc(), - ), - ), -); diff --git a/dart/example_web_legacy/web/favicon.ico b/dart/example_web_legacy/web/favicon.ico deleted file mode 100644 index 7ba349b3e6..0000000000 Binary files a/dart/example_web_legacy/web/favicon.ico and /dev/null differ diff --git a/dart/example_web_legacy/web/index.html b/dart/example_web_legacy/web/index.html deleted file mode 100644 index 68cce903f0..0000000000 --- a/dart/example_web_legacy/web/index.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - dart_web - - - - - - - - - - -
- -
- -
Captured
-
- -
- -
Captured
-
- -
- -
Captured
-
- -
- -
Captured
-
- - - diff --git a/dart/example_web_legacy/web/main.dart b/dart/example_web_legacy/web/main.dart deleted file mode 100644 index f2d303447a..0000000000 --- a/dart/example_web_legacy/web/main.dart +++ /dev/null @@ -1,137 +0,0 @@ -import 'dart:async'; -// ignore: deprecated_member_use -import 'dart:html'; - -import 'package:sentry/sentry.dart'; -import 'package:sentry/src/version.dart'; - -import 'event.dart'; - -// ATTENTION: Change the DSN below with your own to see the events in Sentry. Get one at sentry.io -const dsn = - 'https://e85b375ffb9f43cf8bdf9787768149e0@o447951.ingest.sentry.io/5428562'; - -Future main() async { - await Sentry.init( - (options) => options - ..dsn = dsn - ..debug = true - ..sendDefaultPii = true - ..addEventProcessor(TagEventProcessor()), - appRunner: runApp, - ); -} - -Future runApp() async { - print('runApp'); - - querySelector('#output')?.text = 'Your Dart app is running.'; - - await Sentry.addBreadcrumb( - Breadcrumb( - message: 'Authenticated user', - category: 'auth', - type: 'debug', - data: { - 'admin': true, - 'permissions': [1, 2, 3] - }, - ), - ); - - await Sentry.configureScope((scope) async { - scope - // ..fingerprint = ['example-dart'] - ..transaction = '/example/app' - ..level = SentryLevel.warning; - await scope.setTag('build', '579'); - // ignore: deprecated_member_use - await scope.setExtra('company-name', 'Dart Inc'); - - await scope.setUser( - SentryUser( - id: '800', - username: 'first-user', - email: 'first@user.lan', - // ipAddress: '127.0.0.1', - data: {'first-sign-in': '2020-01-01'}, - ), - ); - }); - - querySelector('#btEvent') - ?.onClick - .listen((event) => captureCompleteExampleEvent()); - querySelector('#btMessage')?.onClick.listen((event) => captureMessage()); - querySelector('#btException')?.onClick.listen((event) => captureException()); - querySelector('#btUnhandledException') - ?.onClick - .listen((event) => captureUnhandledException()); -} - -Future captureMessage() async { - print('Capturing Message : '); - final sentryId = await Sentry.captureMessage( - 'Message 2', - template: 'Message %s', - params: ['2'], - ); - print('capture message result : $sentryId'); - if (sentryId != SentryId.empty()) { - querySelector('#messageResult')?.style.display = 'block'; - } -} - -Future captureException() async { - try { - await buildCard(); - } catch (error, stackTrace) { - print('\nReporting the following stack trace: '); - final sentryId = await Sentry.captureException( - error, - stackTrace: stackTrace, - ); - - print('Capture exception : SentryId: $sentryId'); - - if (sentryId != SentryId.empty()) { - querySelector('#exceptionResult')?.style.display = 'block'; - } - } -} - -Future captureUnhandledException() async { - querySelector('#unhandledResult')?.style.display = 'block'; - - await buildCard(); -} - -Future captureCompleteExampleEvent() async { - print('\nReporting a complete event example: $sdkName'); - final sentryId = await Sentry.captureEvent(event); - - print('Response SentryId: $sentryId'); - - if (sentryId != SentryId.empty()) { - querySelector('#eventResult')?.style.display = 'block'; - } -} - -Future buildCard() async { - await loadData(); -} - -Future loadData() async { - await parseData(); -} - -Future parseData() async { - throw StateError('This is a test error'); -} - -class TagEventProcessor implements EventProcessor { - @override - SentryEvent? apply(SentryEvent event, Hint hint) { - return event..tags?.addAll({'page-locale': 'en-us'}); - } -} diff --git a/dart/example_web_legacy/web/styles.css b/dart/example_web_legacy/web/styles.css deleted file mode 100644 index cc035c95c9..0000000000 --- a/dart/example_web_legacy/web/styles.css +++ /dev/null @@ -1,14 +0,0 @@ -@import url(https://fonts.googleapis.com/css?family=Roboto); - -html, body { - width: 100%; - height: 100%; - margin: 0; - padding: 0; - font-family: 'Roboto', sans-serif; -} - -#output { - padding: 20px; - text-align: center; -} diff --git a/dart/lib/sentry.dart b/dart/lib/sentry.dart index cbfa514b36..81915914ef 100644 --- a/dart/lib/sentry.dart +++ b/dart/lib/sentry.dart @@ -3,62 +3,52 @@ // found in the LICENSE file. /// A pure Dart client for Sentry.io crash reporting. -library sentry_dart; +library; -export 'src/run_zoned_guarded_integration.dart'; +export 'src/event_processor.dart'; +export 'src/exception_cause.dart'; +export 'src/exception_cause_extractor.dart'; +export 'src/exception_stacktrace_extractor.dart'; +export 'src/exception_type_identifier.dart'; +export 'src/hint.dart'; +export 'src/http_client/sentry_http_client.dart'; +export 'src/http_client/sentry_http_client_error.dart'; export 'src/hub.dart'; -// useful for tests export 'src/hub_adapter.dart'; -export 'src/platform_checker.dart'; +export 'src/integration.dart'; export 'src/noop_isolate_error_integration.dart' if (dart.library.io) 'src/isolate_error_integration.dart'; +export 'src/performance_collector.dart'; +export 'src/runtime_checker.dart'; export 'src/protocol.dart'; +export 'src/protocol/sentry_feedback.dart'; +export 'src/protocol/sentry_proxy.dart'; +export 'src/run_zoned_guarded_integration.dart'; export 'src/scope.dart'; export 'src/scope_observer.dart'; export 'src/sentry.dart'; +export 'src/sentry_attachment/sentry_attachment.dart'; +export 'src/sentry_baggage.dart'; +export 'src/sentry_client.dart'; export 'src/sentry_envelope.dart'; export 'src/sentry_envelope_item.dart'; -export 'src/sentry_client.dart'; export 'src/sentry_options.dart'; -// useful for integrations +// ignore: invalid_export_of_internal_element +export 'src/constants.dart'; +// ignore: invalid_export_of_internal_element +export 'src/sentry_trace_origins.dart'; +export 'src/span_data_convention.dart'; +export 'src/spotlight.dart'; export 'src/throwable_mechanism.dart'; -export 'src/transport/transport.dart'; -export 'src/integration.dart'; -export 'src/event_processor.dart'; -export 'src/http_client/sentry_http_client.dart'; -export 'src/http_client/sentry_http_client_error.dart'; -export 'src/sentry_attachment/sentry_attachment.dart'; -export 'src/sentry_user_feedback.dart'; -export 'src/utils/tracing_utils.dart'; -export 'src/performance_collector.dart'; -// tracing export 'src/tracing.dart'; -export 'src/hint.dart'; +export 'src/transport/transport.dart'; export 'src/type_check_hint.dart'; -export 'src/sentry_baggage.dart'; -// exception extraction -export 'src/exception_cause_extractor.dart'; -export 'src/exception_cause.dart'; -export 'src/exception_stacktrace_extractor.dart'; -export 'src/exception_type_identifier.dart'; -// URL -// ignore: invalid_export_of_internal_element -export 'src/utils/http_sanitizer.dart'; // ignore: invalid_export_of_internal_element -export 'src/utils/url_details.dart'; +export 'src/utils.dart'; // ignore: invalid_export_of_internal_element export 'src/utils/http_header_utils.dart'; // ignore: invalid_export_of_internal_element -export 'src/sentry_trace_origins.dart'; -// ignore: invalid_export_of_internal_element -export 'src/sentry_span_operations.dart'; +export 'src/utils/http_sanitizer.dart'; +export 'src/utils/tracing_utils.dart'; // ignore: invalid_export_of_internal_element -export 'src/utils.dart'; -// spotlight debugging -export 'src/spotlight.dart'; -// proxy -export 'src/protocol/sentry_proxy.dart'; -// feedback -export 'src/protocol/sentry_feedback.dart'; -// constants -export 'src/span_data_convention.dart'; +export 'src/utils/url_details.dart'; diff --git a/dart/lib/src/constants.dart b/dart/lib/src/constants.dart new file mode 100644 index 0000000000..caa7641db0 --- /dev/null +++ b/dart/lib/src/constants.dart @@ -0,0 +1,30 @@ +import 'package:meta/meta.dart'; + +@internal +class SentrySpanOperations { + static const String uiLoad = 'ui.load'; + static const String uiTimeToInitialDisplay = 'ui.load.initial_display'; + static const String uiTimeToFullDisplay = 'ui.load.full_display'; + static const String dbSqlQuery = 'db.sql.query'; + static const String dbSqlTransaction = 'db.sql.transaction'; + static const String dbSqlBatch = 'db.sql.batch'; + static const String dbOpen = 'db.open'; + static const String dbClose = 'db.close'; +} + +@internal +class SentrySpanData { + static const String dbSystemKey = 'db.system'; + static const String dbNameKey = 'db.name'; + + static const String dbSystemSqlite = 'db.sqlite'; +} + +@internal +class SentrySpanDescriptions { + static const String dbTransaction = 'Transaction'; + static String dbBatch({required List statements}) => + 'Batch $statements'; + static String dbOpen({required String dbName}) => 'Open database $dbName'; + static String dbClose({required String dbName}) => 'Close database $dbName'; +} diff --git a/dart/lib/src/dart_exception_type_identifier.dart b/dart/lib/src/dart_exception_type_identifier.dart index 59fa6b3db6..9f165ccba4 100644 --- a/dart/lib/src/dart_exception_type_identifier.dart +++ b/dart/lib/src/dart_exception_type_identifier.dart @@ -4,7 +4,6 @@ import 'package:http/http.dart' show ClientException; import '../sentry.dart'; import 'dart_exception_type_identifier_io.dart' - if (dart.library.html) 'dart_exception_type_identifier_web.dart' if (dart.library.js_interop) 'dart_exception_type_identifier_web.dart'; class DartExceptionTypeIdentifier implements ExceptionTypeIdentifier { diff --git a/dart/lib/src/environment/environment_variables.dart b/dart/lib/src/environment/environment_variables.dart index 3dcb1674b3..51c8b1ea0d 100644 --- a/dart/lib/src/environment/environment_variables.dart +++ b/dart/lib/src/environment/environment_variables.dart @@ -1,6 +1,5 @@ -import '../platform_checker.dart'; +import '../runtime_checker.dart'; import '_io_environment_variables.dart' - if (dart.library.html) '_web_environment_variables.dart' if (dart.library.js_interop) '_web_environment_variables.dart' as env; /// Reads environment variables from the system. @@ -29,7 +28,7 @@ abstract class EnvironmentVariables { /// Returns an environment based on the compilation mode of Dart or Flutter. /// This can be set as [SentryOptions.environment] - String environmentForMode(PlatformChecker checker) { + String environmentForMode(RuntimeChecker checker) { // We infer the environment based on the release/non-release and profile // constants. diff --git a/dart/lib/src/event_processor/enricher/enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/enricher_event_processor.dart index 779d64b700..2b42b8f043 100644 --- a/dart/lib/src/event_processor/enricher/enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/enricher_event_processor.dart @@ -1,7 +1,6 @@ import '../../event_processor.dart'; import '../../sentry_options.dart'; import 'io_enricher_event_processor.dart' - if (dart.library.html) 'html_enricher_event_processor.dart' if (dart.library.js_interop) 'web_enricher_event_processor.dart'; abstract class EnricherEventProcessor implements EventProcessor { diff --git a/dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart deleted file mode 100644 index b988c7d14b..0000000000 --- a/dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart +++ /dev/null @@ -1,104 +0,0 @@ -// ignore: deprecated_member_use -import 'dart:html' as html show window, Window; - -import '../../../sentry.dart'; -import 'enricher_event_processor.dart'; - -EnricherEventProcessor enricherEventProcessor(SentryOptions options) { - return WebEnricherEventProcessor( - html.window, - options, - ); -} - -class WebEnricherEventProcessor implements EnricherEventProcessor { - WebEnricherEventProcessor( - this._window, - this._options, - ); - - final html.Window _window; - - final SentryOptions _options; - - @override - SentryEvent? apply(SentryEvent event, Hint hint) { - // Web has no native integration, so no need to check for it - - final contexts = event.contexts.copyWith( - device: _getDevice(event.contexts.device), - culture: _getSentryCulture(event.contexts.culture), - ); - - contexts['dart_context'] = _getDartContext(); - - return event.copyWith( - contexts: contexts, - request: _getRequest(event.request), - transaction: event.transaction ?? _window.location.pathname, - ); - } - - // As seen in - // https://github.com/getsentry/sentry-javascript/blob/a6f8dc26a4c7ae2146ae64995a2018c8578896a6/packages/browser/src/integrations/useragent.ts - SentryRequest _getRequest(SentryRequest? request) { - final requestHeader = request?.headers; - final header = requestHeader == null - ? {} - : Map.from(requestHeader); - - header.putIfAbsent('User-Agent', () => _window.navigator.userAgent); - - final url = request?.url ?? _window.location.toString(); - return (request ?? SentryRequest(url: url)) - .copyWith(headers: header) - .sanitized(); - } - - SentryDevice _getDevice(SentryDevice? device) { - return (device ?? SentryDevice()).copyWith( - online: device?.online ?? _window.navigator.onLine, - memorySize: device?.memorySize ?? _getMemorySize(), - orientation: device?.orientation ?? _getScreenOrientation(), - screenHeightPixels: device?.screenHeightPixels ?? - _window.screen?.available.height.toInt(), - screenWidthPixels: - device?.screenWidthPixels ?? _window.screen?.available.width.toInt(), - screenDensity: - device?.screenDensity ?? _window.devicePixelRatio.toDouble(), - ); - } - - int? _getMemorySize() { - // https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory - final size = _window.navigator.deviceMemory?.toDouble(); - final memoryByteSize = size != null ? size * 1024 * 1024 * 1024 : null; - return memoryByteSize?.toInt(); - } - - SentryOrientation? _getScreenOrientation() { - // https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation - final screenOrientation = _window.screen?.orientation; - if (screenOrientation != null) { - if (screenOrientation.type?.startsWith('portrait') ?? false) { - return SentryOrientation.portrait; - } - if (screenOrientation.type?.startsWith('landscape') ?? false) { - return SentryOrientation.landscape; - } - } - return null; - } - - Map _getDartContext() { - return { - 'compile_mode': _options.platformChecker.compileMode, - }; - } - - SentryCulture _getSentryCulture(SentryCulture? culture) { - return (culture ?? SentryCulture()).copyWith( - timezone: culture?.timezone ?? DateTime.now().timeZoneName, - ); - } -} diff --git a/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart index 62a58352a3..3db395a9a8 100644 --- a/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart @@ -82,25 +82,11 @@ class IoEnricherEventProcessor implements EnricherEventProcessor { String? executable; if (_options.sendDefaultPii) { - try { - // This throws sometimes for some reason - // https://github.com/flutter/flutter/issues/83921 - executable = Platform.executable; - } catch (exception, stackTrace) { - _options.logger( - SentryLevel.error, - 'Platform.executable couldn\'t be retrieved.', - exception: exception, - stackTrace: stackTrace, - ); - if (_options.automatedTestMode) { - rethrow; - } - } + executable = Platform.executable; } return { - 'compile_mode': _options.platformChecker.compileMode, + 'compile_mode': _options.runtimeChecker.compileMode, if (packageConfig != null) 'package_config': packageConfig, // The following information could potentially contain PII if (_options.sendDefaultPii) ...{ diff --git a/dart/lib/src/event_processor/enricher/io_platform_memory.dart b/dart/lib/src/event_processor/enricher/io_platform_memory.dart index 1f4a32987b..5820859f0a 100644 --- a/dart/lib/src/event_processor/enricher/io_platform_memory.dart +++ b/dart/lib/src/event_processor/enricher/io_platform_memory.dart @@ -11,9 +11,9 @@ class PlatformMemory { final SentryOptions options; int? getTotalPhysicalMemory() { - if (options.platformChecker.platform.isLinux) { + if (options.platform.isLinux) { return _getLinuxMemInfoValue('MemTotal'); - } else if (options.platformChecker.platform.isWindows) { + } else if (options.platform.isWindows) { return _getWindowsWmicValue('ComputerSystem', 'TotalPhysicalMemory'); } else { return null; @@ -21,9 +21,9 @@ class PlatformMemory { } int? getFreePhysicalMemory() { - if (options.platformChecker.platform.isLinux) { + if (options.platform.isLinux) { return _getLinuxMemInfoValue('MemFree'); - } else if (options.platformChecker.platform.isWindows) { + } else if (options.platform.isWindows) { return _getWindowsWmicValue('OS', 'FreePhysicalMemory'); } else { return null; diff --git a/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart index 07b7dcd0dd..687a66749f 100644 --- a/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart @@ -1,5 +1,3 @@ -// We would lose compatibility with old dart versions by adding web to pubspec. -// ignore: depend_on_referenced_packages import 'package:web/web.dart' as web show window, Window, Navigator; import '../../../sentry.dart'; @@ -93,7 +91,7 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { Map _getDartContext() { return { - 'compile_mode': _options.platformChecker.compileMode, + 'compile_mode': _options.runtimeChecker.compileMode, }; } diff --git a/dart/lib/src/event_processor/exception/exception_event_processor.dart b/dart/lib/src/event_processor/exception/exception_event_processor.dart index ab4f5e9878..6e65c72391 100644 --- a/dart/lib/src/event_processor/exception/exception_event_processor.dart +++ b/dart/lib/src/event_processor/exception/exception_event_processor.dart @@ -1,7 +1,6 @@ import '../../event_processor.dart'; import '../../sentry_options.dart'; import 'io_exception_event_processor.dart' - if (dart.library.html) 'web_exception_event_processor.dart' if (dart.library.js_interop) 'web_exception_event_processor.dart'; abstract class ExceptionEventProcessor implements EventProcessor { diff --git a/dart/lib/src/hint.dart b/dart/lib/src/hint.dart index 9df1b38365..95a22fd0ad 100644 --- a/dart/lib/src/hint.dart +++ b/dart/lib/src/hint.dart @@ -1,5 +1,7 @@ +import 'protocol/sentry_response.dart'; import 'sentry_attachment/sentry_attachment.dart'; -import 'sentry_options.dart'; + +import 'package:meta/meta.dart'; /// Hints are used in [BeforeSendCallback], [BeforeBreadcrumbCallback] and /// event processors. @@ -41,6 +43,9 @@ import 'sentry_options.dart'; /// }; /// ``` class Hint { + @internal + static const maxResponseBodySize = 157286; + final Map _internalStorage = {}; final List attachments = []; @@ -49,6 +54,8 @@ class Hint { SentryAttachment? viewHierarchy; + SentryResponse? response; + Hint(); factory Hint.withAttachment(SentryAttachment attachment) { @@ -81,6 +88,12 @@ class Hint { return hint; } + factory Hint.withResponse(SentryResponse response) { + final hint = Hint(); + hint.response = response; + return hint; + } + // Key/Value Storage void addAll(Map keysAndValues) { diff --git a/dart/lib/src/hub.dart b/dart/lib/src/hub.dart index ff8e639998..da5c22880f 100644 --- a/dart/lib/src/hub.dart +++ b/dart/lib/src/hub.dart @@ -242,40 +242,6 @@ class Hub { return sentryId; } - @Deprecated( - 'Will be removed in a future version. Use [captureFeedback] instead') - Future captureUserFeedback(SentryUserFeedback userFeedback) async { - if (!_isEnabled) { - _options.logger( - SentryLevel.warning, - "Instance is disabled and this 'captureUserFeedback' call is a no-op.", - ); - return; - } - if (userFeedback.eventId == SentryId.empty()) { - _options.logger( - SentryLevel.warning, - 'Captured UserFeedback with empty id, dropping the feedback', - ); - return; - } - try { - final item = _peek(); - - await item.client.captureUserFeedback(userFeedback); - } catch (exception, stacktrace) { - _options.logger( - SentryLevel.error, - 'Error while capturing user feedback for ${userFeedback.eventId}', - exception: exception, - stackTrace: stacktrace, - ); - if (_options.automatedTestMode) { - rethrow; - } - } - } - /// Captures the feedback. Future captureFeedback( SentryFeedback feedback, { @@ -562,6 +528,7 @@ class Hub { Future captureTransaction( SentryTransaction transaction, { SentryTraceContextHeader? traceContext, + Hint? hint, }) async { var sentryId = SentryId.empty(); @@ -603,6 +570,7 @@ class Hub { transaction, scope: item.scope, traceContext: traceContext, + hint: hint, ); } catch (exception, stackTrace) { _options.logger( diff --git a/dart/lib/src/hub_adapter.dart b/dart/lib/src/hub_adapter.dart index 88b427e376..e831edc834 100644 --- a/dart/lib/src/hub_adapter.dart +++ b/dart/lib/src/hub_adapter.dart @@ -11,7 +11,6 @@ import 'scope.dart'; import 'sentry.dart'; import 'sentry_client.dart'; import 'sentry_options.dart'; -import 'sentry_user_feedback.dart'; import 'tracing.dart'; /// Hub adapter to make Integrations testable @@ -101,21 +100,17 @@ class HubAdapter implements Hub { Future captureTransaction( SentryTransaction transaction, { SentryTraceContextHeader? traceContext, + Hint? hint, }) => Sentry.currentHub.captureTransaction( transaction, traceContext: traceContext, + hint: hint, ); @override ISentrySpan? getSpan() => Sentry.currentHub.getSpan(); - @override - // ignore: deprecated_member_use_from_same_package - Future captureUserFeedback(SentryUserFeedback userFeedback) => - // ignore: deprecated_member_use_from_same_package - Sentry.captureUserFeedback(userFeedback); - @override ISentrySpan startTransactionWithContext( SentryTransactionContext transactionContext, { diff --git a/dart/lib/src/load_dart_debug_images_integration.dart b/dart/lib/src/load_dart_debug_images_integration.dart index 4b7a35c39f..66d33996c0 100644 --- a/dart/lib/src/load_dart_debug_images_integration.dart +++ b/dart/lib/src/load_dart_debug_images_integration.dart @@ -1,8 +1,16 @@ import 'dart:typed_data'; - import 'package:meta/meta.dart'; -import '../sentry.dart'; +import 'event_processor.dart'; +import 'hint.dart'; +import 'hub.dart'; +import 'integration.dart'; +import 'protocol/debug_image.dart'; +import 'protocol/debug_meta.dart'; +import 'protocol/sentry_event.dart'; +import 'protocol/sentry_level.dart'; +import 'protocol/sentry_stack_trace.dart'; +import 'sentry_options.dart'; class LoadDartDebugImagesIntegration extends Integration { @override @@ -83,11 +91,11 @@ class LoadImageIntegrationEventProcessor implements EventProcessor { // It doesn't need to exist and is not used for symbolication. late final String codeFile; - final platform = _options.platformChecker.platform; + final platform = _options.platform; if (platform.isAndroid || platform.isWindows) { type = 'elf'; - debugId = _convertBuildIdToDebugId(stackTrace.buildId!, platform.endian); + debugId = _convertBuildIdToDebugId(stackTrace.buildId!, Endian.host); if (platform.isAndroid) { codeFile = 'libapp.so'; } else if (platform.isWindows) { diff --git a/dart/lib/src/noop_hub.dart b/dart/lib/src/noop_hub.dart index d07e3c9609..a677cbe21d 100644 --- a/dart/lib/src/noop_hub.dart +++ b/dart/lib/src/noop_hub.dart @@ -10,7 +10,6 @@ import 'protocol/sentry_feedback.dart'; import 'scope.dart'; import 'sentry_client.dart'; import 'sentry_options.dart'; -import 'sentry_user_feedback.dart'; import 'tracing.dart'; class NoOpHub implements Hub { @@ -82,13 +81,10 @@ class NoOpHub implements Hub { Future captureTransaction( SentryTransaction transaction, { SentryTraceContextHeader? traceContext, + Hint? hint, }) async => SentryId.empty(); - @override - // ignore: deprecated_member_use_from_same_package - Future captureUserFeedback(SentryUserFeedback userFeedback) async {} - @override Future captureFeedback( SentryFeedback feedback, { diff --git a/dart/lib/src/noop_sentry_client.dart b/dart/lib/src/noop_sentry_client.dart index 7aa9aabe73..39bd728dd9 100644 --- a/dart/lib/src/noop_sentry_client.dart +++ b/dart/lib/src/noop_sentry_client.dart @@ -7,7 +7,6 @@ import 'scope.dart'; import 'sentry_client.dart'; import 'sentry_envelope.dart'; import 'sentry_trace_context_header.dart'; -import 'sentry_user_feedback.dart'; class NoOpSentryClient implements SentryClient { NoOpSentryClient._(); @@ -51,10 +50,6 @@ class NoOpSentryClient implements SentryClient { Future captureEnvelope(SentryEnvelope envelope) async => SentryId.empty(); - @override - // ignore: deprecated_member_use_from_same_package - Future captureUserFeedback(SentryUserFeedback userFeedback) async {} - @override Future close() async {} @@ -63,6 +58,7 @@ class NoOpSentryClient implements SentryClient { SentryTransaction transaction, { Scope? scope, SentryTraceContextHeader? traceContext, + Hint? hint, }) async => SentryId.empty(); diff --git a/dart/lib/src/noop_sentry_span.dart b/dart/lib/src/noop_sentry_span.dart index 2156aeb678..0038d0954d 100644 --- a/dart/lib/src/noop_sentry_span.dart +++ b/dart/lib/src/noop_sentry_span.dart @@ -1,3 +1,4 @@ +import 'hint.dart'; import 'protocol.dart'; import 'tracing.dart'; import 'utils.dart'; @@ -26,7 +27,11 @@ class NoOpSentrySpan extends ISentrySpan { } @override - Future finish({SpanStatus? status, DateTime? endTimestamp}) async {} + Future finish({ + SpanStatus? status, + DateTime? endTimestamp, + Hint? hint, + }) async {} @override void removeData(String key) {} diff --git a/dart/lib/src/origin.dart b/dart/lib/src/origin.dart index 1d5b3dc4bf..65835e7e0a 100644 --- a/dart/lib/src/origin.dart +++ b/dart/lib/src/origin.dart @@ -1,3 +1 @@ -export 'origin_io.dart' - if (dart.library.html) 'origin_html.dart' - if (dart.library.js_interop) 'origin_web.dart'; +export 'origin_io.dart' if (dart.library.js_interop) 'origin_web.dart'; diff --git a/dart/lib/src/origin_html.dart b/dart/lib/src/origin_html.dart deleted file mode 100644 index 43a6a18b11..0000000000 --- a/dart/lib/src/origin_html.dart +++ /dev/null @@ -1,5 +0,0 @@ -// ignore: deprecated_member_use -import 'dart:html'; - -/// request origin, used for browser stacktrace -String get eventOrigin => '${window.location.origin}/'; diff --git a/dart/lib/src/origin_web.dart b/dart/lib/src/origin_web.dart index db99f33c56..0653054b7a 100644 --- a/dart/lib/src/origin_web.dart +++ b/dart/lib/src/origin_web.dart @@ -1,5 +1,3 @@ -// We would lose compatibility with old dart versions by adding web to pubspec. -// ignore: depend_on_referenced_packages import 'package:web/web.dart'; /// request origin, used for browser stacktrace diff --git a/dart/lib/src/platform/_html_platform.dart b/dart/lib/src/platform/_html_platform.dart deleted file mode 100644 index ea9b388e52..0000000000 --- a/dart/lib/src/platform/_html_platform.dart +++ /dev/null @@ -1,53 +0,0 @@ -// ignore: deprecated_member_use -import 'dart:html' as html; - -import 'platform.dart'; - -const Platform instance = WebPlatform(); - -/// [Platform] implementation that delegates to `dart:html`. -class WebPlatform extends Platform { - /// Creates a new [Platform]. - const WebPlatform(); - - @override - String get operatingSystem => _browserPlatform(); - - @override - String get operatingSystemVersion => 'unknown'; - - @override - String get localHostname => html.window.location.hostname ?? 'unknown'; - - String _browserPlatform() { - final navigatorPlatform = - html.window.navigator.platform?.toLowerCase() ?? ''; - if (navigatorPlatform.startsWith('mac')) { - return 'macos'; - } - if (navigatorPlatform.startsWith('win')) { - return 'windows'; - } - if (navigatorPlatform.contains('iphone') || - navigatorPlatform.contains('ipad') || - navigatorPlatform.contains('ipod')) { - return 'ios'; - } - if (navigatorPlatform.contains('android')) { - return 'android'; - } - if (navigatorPlatform.contains('fuchsia')) { - return 'fuchsia'; - } - - // Since some phones can report a window.navigator.platform as Linux, fall - // back to use CSS to disambiguate Android vs Linux desktop. If the CSS - // indicates that a device has a "fine pointer" (mouse) as the primary - // pointing device, then we'll assume desktop linux, and otherwise we'll - // assume Android. - if (html.window.matchMedia('only screen and (pointer: fine)').matches) { - return 'linux'; - } - return 'android'; - } -} diff --git a/dart/lib/src/platform/_io_platform.dart b/dart/lib/src/platform/_io_platform.dart index ecc9c2035c..fa8f0f5ea2 100644 --- a/dart/lib/src/platform/_io_platform.dart +++ b/dart/lib/src/platform/_io_platform.dart @@ -1,20 +1,33 @@ -import 'dart:io' as io show Platform; +import 'dart:io' as io; import 'platform.dart'; -const Platform instance = IOPlatform(); - /// [Platform] implementation that delegates directly to `dart:io`. -class IOPlatform extends Platform { - /// Creates a new [IOPlatform]. - const IOPlatform(); +class PlatformBase { + const PlatformBase(); - @override - String get operatingSystem => io.Platform.operatingSystem; + OperatingSystem get operatingSystem { + switch (io.Platform.operatingSystem) { + case 'macos': + return OperatingSystem.macos; + case 'windows': + return OperatingSystem.windows; + case 'linux': + return OperatingSystem.linux; + case 'android': + return OperatingSystem.android; + case 'ios': + return OperatingSystem.ios; + case 'fuchsia': + return OperatingSystem.fuchsia; + default: + return OperatingSystem.unknown; + } + } - @override - String get operatingSystemVersion => io.Platform.operatingSystemVersion; + String? get operatingSystemVersion => io.Platform.operatingSystemVersion; - @override String get localHostname => io.Platform.localHostname; + + bool get isWeb => false; } diff --git a/dart/lib/src/platform/_web_platform.dart b/dart/lib/src/platform/_web_platform.dart index da403b254d..56325fa25b 100644 --- a/dart/lib/src/platform/_web_platform.dart +++ b/dart/lib/src/platform/_web_platform.dart @@ -1,43 +1,31 @@ -// We would lose compatibility with old dart versions by adding web to pubspec. -// ignore: depend_on_referenced_packages import 'package:web/web.dart' as web; import 'platform.dart'; -const Platform instance = WebPlatform(); - /// [Platform] implementation that delegates to `dart:web`. -class WebPlatform extends Platform { - /// Creates a new [Platform]. - const WebPlatform(); - - @override - String get operatingSystem => _browserPlatform(); +class PlatformBase { + const PlatformBase(); - @override - String get operatingSystemVersion => 'unknown'; - - @override - String get localHostname => web.window.location.hostname; + bool get isWeb => true; - String _browserPlatform() { + OperatingSystem get operatingSystem { final navigatorPlatform = web.window.navigator.platform.toLowerCase(); if (navigatorPlatform.startsWith('mac')) { - return 'macos'; + return OperatingSystem.macos; } if (navigatorPlatform.startsWith('win')) { - return 'windows'; + return OperatingSystem.windows; } if (navigatorPlatform.contains('iphone') || navigatorPlatform.contains('ipad') || navigatorPlatform.contains('ipod')) { - return 'ios'; + return OperatingSystem.ios; } if (navigatorPlatform.contains('android')) { - return 'android'; + return OperatingSystem.android; } if (navigatorPlatform.contains('fuchsia')) { - return 'fuchsia'; + return OperatingSystem.fuchsia; } // Since some phones can report a window.navigator.platform as Linux, fall @@ -46,8 +34,12 @@ class WebPlatform extends Platform { // pointing device, then we'll assume desktop linux, and otherwise we'll // assume Android. if (web.window.matchMedia('only screen and (pointer: fine)').matches) { - return 'linux'; + return OperatingSystem.linux; } - return 'android'; + return OperatingSystem.android; } + + String? get operatingSystemVersion => null; + + String get localHostname => web.window.location.hostname; } diff --git a/dart/lib/src/platform/mock_platform.dart b/dart/lib/src/platform/mock_platform.dart new file mode 100644 index 0000000000..99b3ef81cc --- /dev/null +++ b/dart/lib/src/platform/mock_platform.dart @@ -0,0 +1,52 @@ +import 'platform.dart'; + +class MockPlatform extends Platform { + @override + late final bool isWeb; + + @override + late final OperatingSystem operatingSystem; + + @override + late final String? operatingSystemVersion; + + @override + late final bool supportsNativeIntegration; + + MockPlatform( + {OperatingSystem? operatingSystem, + String? operatingSystemVersion, + bool? isWeb, + bool? supportsNativeIntegration}) { + this.isWeb = isWeb ?? super.isWeb; + this.operatingSystem = operatingSystem ?? super.operatingSystem; + this.operatingSystemVersion = + operatingSystemVersion ?? super.operatingSystemVersion; + this.supportsNativeIntegration = + supportsNativeIntegration ?? super.supportsNativeIntegration; + } + + factory MockPlatform.android({bool isWeb = false}) { + return MockPlatform(operatingSystem: OperatingSystem.android, isWeb: isWeb); + } + + factory MockPlatform.iOS({bool isWeb = false}) { + return MockPlatform(operatingSystem: OperatingSystem.ios, isWeb: isWeb); + } + + factory MockPlatform.macOS({bool isWeb = false}) { + return MockPlatform(operatingSystem: OperatingSystem.macos, isWeb: isWeb); + } + + factory MockPlatform.linux({bool isWeb = false}) { + return MockPlatform(operatingSystem: OperatingSystem.linux, isWeb: isWeb); + } + + factory MockPlatform.windows({bool isWeb = false}) { + return MockPlatform(operatingSystem: OperatingSystem.windows, isWeb: isWeb); + } + + factory MockPlatform.fuchsia({bool isWeb = false}) { + return MockPlatform(operatingSystem: OperatingSystem.fuchsia, isWeb: isWeb); + } +} diff --git a/dart/lib/src/platform/platform.dart b/dart/lib/src/platform/platform.dart index ab2f94dd5f..ea0ed3fdf7 100644 --- a/dart/lib/src/platform/platform.dart +++ b/dart/lib/src/platform/platform.dart @@ -1,42 +1,30 @@ -import 'dart:typed_data'; +import '_io_platform.dart' if (dart.library.js_interop) '_web_platform.dart' + as impl; -import '_io_platform.dart' - if (dart.library.html) '_html_platform.dart' - if (dart.library.js_interop) '_web_platform.dart' as platform; - -const Platform instance = platform.instance; - -abstract class Platform { +class Platform extends impl.PlatformBase { const Platform(); - /// A string (`linux`, `macos`, `windows`, `android`, `ios`, or `fuchsia`) - /// representing the operating system. - String get operatingSystem; - - /// A string representing the version of the operating system or platform. - String get operatingSystemVersion; + bool get isLinux => operatingSystem == OperatingSystem.linux; - /// Get the local hostname for the system. - String get localHostname; + bool get isMacOS => operatingSystem == OperatingSystem.macos; - /// Endianness of this platform. - Endian get endian => Endian.host; + bool get isWindows => operatingSystem == OperatingSystem.windows; - /// True if the operating system is Linux. - bool get isLinux => (operatingSystem == 'linux'); + bool get isAndroid => operatingSystem == OperatingSystem.android; - /// True if the operating system is OS X. - bool get isMacOS => (operatingSystem == 'macos'); + bool get isIOS => operatingSystem == OperatingSystem.ios; - /// True if the operating system is Windows. - bool get isWindows => (operatingSystem == 'windows'); + bool get isFuchsia => operatingSystem == OperatingSystem.fuchsia; - /// True if the operating system is Android. - bool get isAndroid => (operatingSystem == 'android'); - - /// True if the operating system is iOS. - bool get isIOS => (operatingSystem == 'ios'); + bool get supportsNativeIntegration => !isFuchsia; +} - /// True if the operating system is Fuchsia - bool get isFuchsia => (operatingSystem == 'fuchsia'); +enum OperatingSystem { + android, + fuchsia, + ios, + linux, + macos, + windows, + unknown, } diff --git a/dart/lib/src/protocol/contexts.dart b/dart/lib/src/protocol/contexts.dart index 0a38e505af..d15c06b418 100644 --- a/dart/lib/src/protocol/contexts.dart +++ b/dart/lib/src/protocol/contexts.dart @@ -137,9 +137,10 @@ class Contexts extends MapView { set trace(SentryTraceContext? trace) => this[SentryTraceContext.type] = trace; - /// Response context for a HTTP response. + /// Response context for a HTTP response. Not added automatically. SentryResponse? get response => this[SentryResponse.type]; + /// Use [Hint.response] in `beforeSend/beforeSendTransaction` to populate this value. set response(SentryResponse? value) => this[SentryResponse.type] = value; /// Feedback context for a feedback event. diff --git a/dart/lib/src/protocol/sdk_version.dart b/dart/lib/src/protocol/sdk_version.dart index b915fbdde8..a65e29927c 100644 --- a/dart/lib/src/protocol/sdk_version.dart +++ b/dart/lib/src/protocol/sdk_version.dart @@ -71,6 +71,7 @@ class SdkVersion { final json = AccessAwareMap(data); final packagesJson = json['packages'] as List?; final integrationsJson = json['integrations'] as List?; + return SdkVersion( name: json['name'], version: json['version'], diff --git a/dart/lib/src/protocol/sentry_event.dart b/dart/lib/src/protocol/sentry_event.dart index f741097e08..b1bda25804 100644 --- a/dart/lib/src/protocol/sentry_event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -99,9 +99,8 @@ class SentryEvent with SentryEventLike { /// If it's an Error, with a stackTrace, the stackTrace is logged. /// If this behavior is undesirable, consider using a custom formatted /// [message] instead. - dynamic get throwable => (_throwable is ThrowableMechanism) - ? (_throwable as ThrowableMechanism).throwable - : _throwable; + dynamic get throwable => + (_throwable is ThrowableMechanism) ? _throwable.throwable : _throwable; /// A throwable decorator that holds a [Mechanism] related to the decorated /// [throwable] diff --git a/dart/lib/src/protocol/sentry_span.dart b/dart/lib/src/protocol/sentry_span.dart index 52d1b949a8..fb650d0f4a 100644 --- a/dart/lib/src/protocol/sentry_span.dart +++ b/dart/lib/src/protocol/sentry_span.dart @@ -5,7 +5,8 @@ import 'package:meta/meta.dart'; import '../../sentry.dart'; import '../sentry_tracer.dart'; -typedef OnFinishedCallback = Future Function({DateTime? endTimestamp}); +typedef OnFinishedCallback = Future Function( + {DateTime? endTimestamp, Hint? hint}); class SentrySpan extends ISentrySpan { final SentrySpanContext _context; @@ -48,7 +49,8 @@ class SentrySpan extends ISentrySpan { } @override - Future finish({SpanStatus? status, DateTime? endTimestamp}) async { + Future finish( + {SpanStatus? status, DateTime? endTimestamp, Hint? hint}) async { if (finished) { return; } @@ -83,8 +85,9 @@ class SentrySpan extends ISentrySpan { if (_throwable != null) { _hub.setSpanContext(_throwable, this, _tracer.name); } - await _finishedCallback?.call(endTimestamp: _endTimestamp); - return super.finish(status: status, endTimestamp: _endTimestamp); + await _finishedCallback?.call(endTimestamp: _endTimestamp, hint: hint); + return super + .finish(status: status, endTimestamp: _endTimestamp, hint: hint); } @override diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index a62d7b9c58..aa5455c594 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -25,7 +25,6 @@ import 'access_aware_map.dart'; /// "username": "my_user", /// "email": "foo@example.com", /// "ip_address": "127.0.0.1", -/// "segment": "segment" /// } /// ``` @immutable @@ -39,20 +38,16 @@ class SentryUser { this.username, this.email, this.ipAddress, - this.segment, this.geo, this.name, Map? data, @Deprecated('Will be removed in v8. Use [data] instead') Map? extras, this.unknown, - }) : assert( - id != null || - username != null || - email != null || - ipAddress != null || - segment != null, - ), + }) : assert(id != null || + username != null || + email != null || + ipAddress != null), data = data == null ? null : Map.from(data), // ignore: deprecated_member_use_from_same_package extras = extras == null ? null : Map.from(extras); @@ -69,11 +64,6 @@ class SentryUser { /// The IP of the user. final String? ipAddress; - /// The user segment, for apps that divide users in user segments. - @Deprecated( - 'Will be removed in v9. Use a custom tag or context instead to capture this information.') - final String? segment; - /// Any other user context information that may be helpful. /// /// These keys are stored as extra information but not specifically processed @@ -121,7 +111,6 @@ class SentryUser { username: json['username'], email: json['email'], ipAddress: json['ip_address'], - segment: json['segment'], data: data, geo: geo, name: json['name'], @@ -140,8 +129,6 @@ class SentryUser { if (username != null) 'username': username, if (email != null) 'email': email, if (ipAddress != null) 'ip_address': ipAddress, - // ignore: deprecated_member_use_from_same_package - if (segment != null) 'segment': segment, if (data?.isNotEmpty ?? false) 'data': data, // ignore: deprecated_member_use_from_same_package if (extras?.isNotEmpty ?? false) 'extras': extras, @@ -155,7 +142,6 @@ class SentryUser { String? username, String? email, String? ipAddress, - String? segment, @Deprecated('Will be removed in v8. Use [data] instead') Map? extras, String? name, @@ -167,8 +153,6 @@ class SentryUser { username: username ?? this.username, email: email ?? this.email, ipAddress: ipAddress ?? this.ipAddress, - // ignore: deprecated_member_use_from_same_package - segment: segment ?? this.segment, data: data ?? this.data, // ignore: deprecated_member_use_from_same_package extras: extras ?? this.extras, diff --git a/dart/lib/src/platform_checker.dart b/dart/lib/src/runtime_checker.dart similarity index 51% rename from dart/lib/src/platform_checker.dart rename to dart/lib/src/runtime_checker.dart index 884775a95a..4aee63c8fd 100644 --- a/dart/lib/src/platform_checker.dart +++ b/dart/lib/src/runtime_checker.dart @@ -1,18 +1,11 @@ import 'dart:async'; -import 'platform/platform.dart'; - /// Helper to check in which environment the library is running. /// The environment checks (release/debug/profile) are mutually exclusive. -class PlatformChecker { - static const _jsUtil = 'dart.library.js_util'; - - PlatformChecker({ - this.platform = instance, - bool? isWeb, +class RuntimeChecker { + RuntimeChecker({ bool? isRootZone, - }) : isWeb = isWeb ?? _isWebWithWasmSupport(), - isRootZone = isRootZone ?? Zone.current == Zone.root; + }) : isRootZone = isRootZone ?? Zone.current == Zone.root; /// Check if running in release/production environment bool isReleaseMode() { @@ -29,7 +22,6 @@ class PlatformChecker { return const bool.fromEnvironment('dart.vm.profile', defaultValue: false); } - final bool isWeb; final bool isRootZone; String get compileMode { @@ -39,22 +31,4 @@ class PlatformChecker { ? 'debug' : 'profile'; } - - /// Indicates whether a native integration is available. - bool get hasNativeIntegration => - isWeb || - platform.isAndroid || - platform.isIOS || - platform.isMacOS || - platform.isWindows || - platform.isLinux; - - static bool _isWebWithWasmSupport() { - if (const bool.hasEnvironment(_jsUtil)) { - return const bool.fromEnvironment(_jsUtil); - } - return identical(0, 0.0); - } - - final Platform platform; } diff --git a/dart/lib/src/sentry.dart b/dart/lib/src/sentry.dart index 7b62938c96..d89d26c46c 100644 --- a/dart/lib/src/sentry.dart +++ b/dart/lib/src/sentry.dart @@ -22,7 +22,6 @@ import 'sentry_attachment/sentry_attachment.dart'; import 'sentry_client.dart'; import 'sentry_options.dart'; import 'sentry_run_zoned_guarded.dart'; -import 'sentry_user_feedback.dart'; import 'tracing.dart'; import 'transport/data_category.dart'; import 'transport/task_queue.dart'; @@ -88,13 +87,13 @@ class Sentry { _setEnvironmentVariables(options); // Throws when running on the browser - if (!options.platformChecker.isWeb) { + if (!options.platform.isWeb) { // catch any errors that may occur within the entry function, main() // in the ‘root zone’ where all Dart programs start options.addIntegrationByIndex(0, IsolateErrorIntegration()); } - if (options.platformChecker.isDebugMode()) { + if (options.runtimeChecker.isDebugMode()) { options.debug = true; options.logger( SentryLevel.debug, @@ -124,7 +123,7 @@ class Sentry { options.dsn = options.dsn ?? vars.dsn; if (options.environment == null) { - var environment = vars.environmentForMode(options.platformChecker); + var environment = vars.environmentForMode(options.runtimeChecker); options.environment = vars.environment ?? environment; } @@ -249,14 +248,6 @@ class Sentry { DataCategory.unknown, ); - /// Reports a [userFeedback] to Sentry.io. - /// - /// First capture an event and use the [SentryId] to create a [SentryUserFeedback] - @Deprecated( - 'Will be removed in a future version. Use [captureFeedback] instead') - static Future captureUserFeedback(SentryUserFeedback userFeedback) => - _hub.captureUserFeedback(userFeedback); - /// Reports [SentryFeedback] to Sentry.io. /// /// Use [withScope] to add [SentryAttachment] to the feedback. diff --git a/dart/lib/src/sentry_baggage.dart b/dart/lib/src/sentry_baggage.dart index 8def45ca0f..8eedee0dc9 100644 --- a/dart/lib/src/sentry_baggage.dart +++ b/dart/lib/src/sentry_baggage.dart @@ -1,4 +1,5 @@ import 'package:meta/meta.dart'; + import 'protocol.dart'; import 'scope.dart'; import 'sentry_options.dart'; @@ -106,11 +107,6 @@ class SentryBaggage { if (scope.user?.id != null) { setUserId(scope.user!.id!); } - // ignore: deprecated_member_use_from_same_package - if (scope.user?.segment != null) { - // ignore: deprecated_member_use_from_same_package - setUserSegment(scope.user!.segment!); - } if (scope.replayId != null && scope.replayId != SentryId.empty()) { setReplayId(scope.replayId.toString()); } @@ -181,12 +177,6 @@ class SentryBaggage { set('sentry-user_id', value); } - @Deprecated( - 'Will be removed in v9 since functionality has been removed from Sentry') - void setUserSegment(String value) { - set('sentry-user_segment', value); - } - void setTransaction(String value) { set('sentry-transaction', value); } diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index bef31c1e9f..20bbbd5c9a 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -17,7 +17,6 @@ import 'sentry_exception_factory.dart'; import 'sentry_options.dart'; import 'sentry_stack_trace_factory.dart'; import 'sentry_trace_context_header.dart'; -import 'sentry_user_feedback.dart'; import 'transport/client_report_transport.dart'; import 'transport/data_category.dart'; import 'transport/http_transport.dart'; @@ -66,11 +65,11 @@ class SentryClient { options, options.transport, ); - // TODO: Web might change soon to use the JS SDK so we can remove it here later on + // TODO: Use spotlight integration directly through JS SDK, then we can remove isWeb check final enableFlutterSpotlight = (options.spotlight.enabled && - (options.platformChecker.isWeb || - options.platformChecker.platform.isLinux || - options.platformChecker.platform.isWindows)); + (options.platform.isWeb || + options.platform.isLinux || + options.platform.isWindows)); // Spotlight in the Flutter layer is only enabled for Web, Linux and Windows // Other platforms use spotlight through their native SDKs if (enableFlutterSpotlight) { @@ -215,7 +214,7 @@ class SentryClient { environment: event.environment ?? _options.environment, release: event.release ?? _options.release, sdk: event.sdk ?? _options.sdk, - platform: event.platform ?? sdkPlatform(_options.platformChecker.isWeb), + platform: event.platform ?? sdkPlatform(_options.platform.isWeb), ); if (event is SentryTransaction) { @@ -250,7 +249,7 @@ class SentryClient { SentryThread? sentryThread; - if (!_options.platformChecker.isWeb && + if (!_options.platform.isWeb && isolateName != null && _options.attachThreads) { sentryException = sentryException.copyWith(threadId: isolateId); @@ -365,8 +364,9 @@ class SentryClient { SentryTransaction transaction, { Scope? scope, SentryTraceContextHeader? traceContext, + Hint? hint, }) async { - final hint = Hint(); + hint ??= Hint(); SentryTransaction? preparedTransaction = _prepareEvent(transaction, hint) as SentryTransaction; @@ -452,18 +452,6 @@ class SentryClient { return _options.transport.send(envelope); } - /// Reports the [userFeedback] to Sentry.io. - @Deprecated( - 'Will be removed in a future version. Use [captureFeedback] instead') - Future captureUserFeedback(SentryUserFeedback userFeedback) { - final envelope = SentryEnvelope.fromUserFeedback( - userFeedback, - _options.sdk, - dsn: _options.dsn, - ); - return _options.transport.send(envelope); - } - /// Reports the [feedback] to Sentry.io. Future captureFeedback( SentryFeedback feedback, { @@ -503,7 +491,7 @@ class SentryClient { try { if (event is SentryTransaction && beforeSendTransaction != null) { beforeSendName = 'beforeSendTransaction'; - final callbackResult = beforeSendTransaction(event); + final callbackResult = beforeSendTransaction(event, hint); if (callbackResult is Future) { processedEvent = await callbackResult; } else { @@ -564,7 +552,7 @@ class SentryClient { bool _sampleRate() { if (_options.sampleRate != null && _random != null) { - return (_options.sampleRate! < _random!.nextDouble()); + return (_options.sampleRate! < _random.nextDouble()); } return false; } diff --git a/dart/lib/src/sentry_envelope.dart b/dart/lib/src/sentry_envelope.dart index 5d83797143..10d4b3a085 100644 --- a/dart/lib/src/sentry_envelope.dart +++ b/dart/lib/src/sentry_envelope.dart @@ -8,7 +8,6 @@ import 'sentry_envelope_item.dart'; import 'sentry_item_type.dart'; import 'sentry_options.dart'; import 'sentry_trace_context_header.dart'; -import 'sentry_user_feedback.dart'; import 'utils.dart'; /// Class representation of `Envelope` file. @@ -59,23 +58,6 @@ class SentryEnvelope { ); } - @Deprecated('Will be removed in a future version.') - factory SentryEnvelope.fromUserFeedback( - SentryUserFeedback feedback, - SdkVersion sdkVersion, { - String? dsn, - }) { - return SentryEnvelope( - // no need for [traceContext] - SentryEnvelopeHeader( - feedback.eventId, - sdkVersion, - dsn: dsn, - ), - [SentryEnvelopeItem.fromUserFeedback(feedback)], - ); - } - /// Create a [SentryEnvelope] containing one [SentryEnvelopeItem] which holds the [SentryTransaction] data. factory SentryEnvelope.fromTransaction( SentryTransaction transaction, diff --git a/dart/lib/src/sentry_envelope_item.dart b/dart/lib/src/sentry_envelope_item.dart index 03164ba2a8..bfe4d818eb 100644 --- a/dart/lib/src/sentry_envelope_item.dart +++ b/dart/lib/src/sentry_envelope_item.dart @@ -5,7 +5,6 @@ import 'protocol.dart'; import 'sentry_attachment/sentry_attachment.dart'; import 'sentry_envelope_item_header.dart'; import 'sentry_item_type.dart'; -import 'sentry_user_feedback.dart'; import 'utils.dart'; /// Item holding header information and JSON encoded data. @@ -40,22 +39,6 @@ class SentryEnvelopeItem { ); } - /// Create a [SentryEnvelopeItem] which sends [SentryUserFeedback]. - @Deprecated('Will be removed in a future version.') - factory SentryEnvelopeItem.fromUserFeedback(SentryUserFeedback feedback) { - final dataFactory = () => utf8JsonEncoder.convert(feedback.toJson()); - - final header = SentryEnvelopeItemHeader( - SentryItemType.userFeedback, - contentType: 'application/json', - ); - return SentryEnvelopeItem( - header, - dataFactory, - originalObject: feedback, - ); - } - /// Create a [SentryEnvelopeItem] which holds the [SentryEvent] data. factory SentryEnvelopeItem.fromEvent(SentryEvent event) { return SentryEnvelopeItem( diff --git a/dart/lib/src/sentry_item_type.dart b/dart/lib/src/sentry_item_type.dart index 18dbc8f4ad..d6bf2a31de 100644 --- a/dart/lib/src/sentry_item_type.dart +++ b/dart/lib/src/sentry_item_type.dart @@ -1,6 +1,5 @@ class SentryItemType { static const String event = 'event'; - static const String userFeedback = 'user_report'; static const String attachment = 'attachment'; static const String transaction = 'transaction'; static const String clientReport = 'client_report'; diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 6a3d9f371f..4f560e3e23 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -10,6 +10,7 @@ import 'client_reports/noop_client_report_recorder.dart'; import 'diagnostic_logger.dart'; import 'environment/environment_variables.dart'; import 'noop_client.dart'; +import 'platform/platform.dart'; import 'sentry_exception_factory.dart'; import 'sentry_stack_trace_factory.dart'; import 'transport/noop_transport.dart'; @@ -124,11 +125,6 @@ class SentryOptions { /// This does not change whether an event is captured. MaxRequestBodySize maxRequestBodySize = MaxRequestBodySize.never; - /// Configures up to which size response bodies should be included in events. - /// This does not change whether an event is captured. - MaxResponseBodySize maxResponseBodySize = MaxResponseBodySize.never; - - // ignore: deprecated_member_use_from_same_package SentryLogger _logger = noOpLogger; /// Logger interface to log useful debugging information if debug is enabled @@ -159,12 +155,10 @@ class SentryOptions { set debug(bool newValue) { _debug = newValue; - // ignore: deprecated_member_use_from_same_package if (_debug == true && logger == noOpLogger) { _logger = _debugLogger; } if (_debug == false && logger == _debugLogger) { - // ignore: deprecated_member_use_from_same_package _logger = noOpLogger; } } @@ -278,9 +272,12 @@ class SentryOptions { /// `debugPrint` calls are only recorded in release builds, though. bool enablePrintBreadcrumbs = true; - /// If [platformChecker] is provided, it is used get the environment. - /// This is useful in tests. Should be an implementation of [PlatformChecker]. - PlatformChecker platformChecker = PlatformChecker(); + /// If [runtimeChecker] is provided, it is used get the environment. + /// This is useful in tests. Should be an implementation of [RuntimeChecker]. + RuntimeChecker runtimeChecker = RuntimeChecker(); + + /// Info on which platform the SDK runs. + Platform platform = Platform(); /// If [environmentVariables] is provided, it is used get the environment /// variables. This is useful in tests. @@ -444,13 +441,6 @@ class SentryOptions { _stackTraceExtractorsByType[extractor.exceptionType] = extractor; } - /// Enables generation of transactions and propagation of trace data. If set - /// to null, tracing might be enabled if [tracesSampleRate] or [tracesSampler] - /// are set. - @Deprecated( - 'Use either tracesSampleRate or tracesSampler instead. This will be removed in v9') - bool? enableTracing; - /// Only for internal use. Changed SDK behaviour when set to true: /// - Rethrow exceptions that occur in user provided closures @internal @@ -508,12 +498,15 @@ class SentryOptions { /// iOS only supports http proxies, while macOS also supports socks. SentryProxy? proxy; - SentryOptions({String? dsn, PlatformChecker? checker}) { + SentryOptions({String? dsn, Platform? platform, RuntimeChecker? checker}) { this.dsn = dsn; + if (platform != null) { + this.platform = platform; + } if (checker != null) { - platformChecker = checker; + runtimeChecker = checker; } - sdk = SdkVersion(name: sdkName(platformChecker.isWeb), version: sdkVersion); + sdk = SdkVersion(name: sdkName(this.platform.isWeb), version: sdkVersion); sdk.addPackage('pub:sentry', sdkVersion); } @@ -560,11 +553,6 @@ class SentryOptions { /// Returns if tracing should be enabled. If tracing is disabled, starting transactions returns /// [NoOpSentrySpan]. bool isTracingEnabled() { - // ignore: deprecated_member_use_from_same_package - final enable = enableTracing; - if (enable != null) { - return enable; - } return tracesSampleRate != null || tracesSampler != null; } @@ -601,6 +589,15 @@ class SentryOptions { } } +@visibleForTesting +void noOpLogger( + SentryLevel level, + String message, { + String? logger, + Object? exception, + StackTrace? stackTrace, +}) {} + /// This function is called with an SDK specific event object and can return a modified event /// object or nothing to skip reporting the event typedef BeforeSendCallback = FutureOr Function( @@ -612,6 +609,7 @@ typedef BeforeSendCallback = FutureOr Function( /// object or nothing to skip reporting the transaction typedef BeforeSendTransactionCallback = FutureOr Function( SentryTransaction transaction, + Hint hint, ); /// This function is called with an SDK specific breadcrumb object before the breadcrumb is added @@ -642,32 +640,3 @@ typedef SentryLogger = void Function( typedef TracesSamplerCallback = double? Function( SentrySamplingContext samplingContext); - -/// A NoOp logger that does nothing -@Deprecated('Will be removed in v8. Disable [debug] instead') -void noOpLogger( - SentryLevel level, - String message, { - String? logger, - Object? exception, - StackTrace? stackTrace, -}) {} - -/// A Logger that prints out the level and message -@Deprecated('Will be removed in v8. Enable [debug] instead') -void dartLogger( - SentryLevel level, - String message, { - String? logger, - Object? exception, - StackTrace? stackTrace, -}) { - log( - '[${level.name}] $message', - level: level.toDartLogLevel(), - name: logger ?? 'sentry', - time: getUtcDateTime(), - error: exception, - stackTrace: stackTrace, - ); -} diff --git a/dart/lib/src/sentry_run_zoned_guarded.dart b/dart/lib/src/sentry_run_zoned_guarded.dart index 7c23824e11..d71d688c22 100644 --- a/dart/lib/src/sentry_run_zoned_guarded.dart +++ b/dart/lib/src/sentry_run_zoned_guarded.dart @@ -47,7 +47,7 @@ class SentryRunZonedGuarded { // This happens for example if: // - hub.addBreadcrumb() called print() itself // - This happens for example if hub.isEnabled == false and - // options.logger == dartLogger + // options.logger == _debugLogger // // Anyway, in order to not cause a stack overflow due to recursion // we drop any further print() call while adding a breadcrumb. diff --git a/dart/lib/src/sentry_span_interface.dart b/dart/lib/src/sentry_span_interface.dart index f6c36c49e7..a377310b79 100644 --- a/dart/lib/src/sentry_span_interface.dart +++ b/dart/lib/src/sentry_span_interface.dart @@ -1,5 +1,6 @@ import 'package:meta/meta.dart'; +import 'hint.dart'; import 'protocol.dart'; import 'tracing.dart'; @@ -25,7 +26,11 @@ abstract class ISentrySpan { void removeData(String key); /// Sets span timestamp marking this span as finished. - Future finish({SpanStatus? status, DateTime? endTimestamp}) async {} + Future finish({ + SpanStatus? status, + DateTime? endTimestamp, + Hint? hint, + }) async {} /// Gets span status. SpanStatus? get status; diff --git a/dart/lib/src/sentry_span_operations.dart b/dart/lib/src/sentry_span_operations.dart deleted file mode 100644 index 27b1d22496..0000000000 --- a/dart/lib/src/sentry_span_operations.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:meta/meta.dart'; - -@internal -class SentrySpanOperations { - static const String uiLoad = 'ui.load'; - static const String uiTimeToInitialDisplay = 'ui.load.initial_display'; - static const String uiTimeToFullDisplay = 'ui.load.full_display'; -} diff --git a/dart/lib/src/sentry_stack_trace_factory.dart b/dart/lib/src/sentry_stack_trace_factory.dart index 36c93e5fc0..431e065ed9 100644 --- a/dart/lib/src/sentry_stack_trace_factory.dart +++ b/dart/lib/src/sentry_stack_trace_factory.dart @@ -127,7 +127,7 @@ class SentryStackTraceFactory { SentryLevel.debug, "Failed to parse stack frame: $member"); } - final platform = _options.platformChecker.isWeb ? 'javascript' : 'dart'; + final platform = _options.platform.isWeb ? 'javascript' : 'dart'; final fileName = frame.uri.pathSegments.isNotEmpty ? frame.uri.pathSegments.last : null; final abs = '$eventOrigin${_absolutePathForCrashReport(frame)}'; diff --git a/dart/lib/src/sentry_trace_context_header.dart b/dart/lib/src/sentry_trace_context_header.dart index c80aae9fea..370dd0a94b 100644 --- a/dart/lib/src/sentry_trace_context_header.dart +++ b/dart/lib/src/sentry_trace_context_header.dart @@ -12,7 +12,6 @@ class SentryTraceContextHeader { this.release, this.environment, this.userId, - this.userSegment, this.transaction, this.sampleRate, this.sampleRand, @@ -26,9 +25,6 @@ class SentryTraceContextHeader { final String? release; final String? environment; final String? userId; - @Deprecated( - 'Will be removed in v9 since functionality has been removed from Sentry') - final String? userSegment; final String? transaction; final String? sampleRate; final String? sampleRand; @@ -49,7 +45,6 @@ class SentryTraceContextHeader { release: json['release'], environment: json['environment'], userId: json['user_id'], - userSegment: json['user_segment'], transaction: json['transaction'], sampleRate: json['sample_rate'], sampled: json['sampled'], @@ -68,8 +63,6 @@ class SentryTraceContextHeader { if (release != null) 'release': release, if (environment != null) 'environment': environment, if (userId != null) 'user_id': userId, - // ignore: deprecated_member_use_from_same_package - if (userSegment != null) 'user_segment': userSegment, if (transaction != null) 'transaction': transaction, if (sampleRate != null) 'sample_rate': sampleRate, if (sampled != null) 'sampled': sampled, @@ -93,11 +86,6 @@ class SentryTraceContextHeader { if (userId != null) { baggage.setUserId(userId!); } - // ignore: deprecated_member_use_from_same_package - if (userSegment != null) { - // ignore: deprecated_member_use_from_same_package - baggage.setUserSegment(userSegment!); - } if (transaction != null) { baggage.setTransaction(transaction!); } diff --git a/dart/lib/src/sentry_trace_origins.dart b/dart/lib/src/sentry_trace_origins.dart index 4377fa2c03..23359bf9f2 100644 --- a/dart/lib/src/sentry_trace_origins.dart +++ b/dart/lib/src/sentry_trace_origins.dart @@ -24,9 +24,7 @@ class SentryTraceOrigins { static const autoDbHiveBoxBase = 'auto.db.hive.box_base'; static const autoDbHiveLazyBox = 'auto.db.hive.lazy_box'; static const autoDbHiveBoxCollection = 'auto.db.hive.box_collection'; - static const autoDbDriftQueryExecutor = 'auto.db.drift.query.executor'; - static const autoDbDriftTransactionExecutor = - 'auto.db.drift.transaction.executor'; + static const autoDbDriftQueryInterceptor = 'auto.db.drift.query.interceptor'; static const autoUiTimeToDisplay = 'auto.ui.time_to_display'; static const manualUiTimeToDisplay = 'manual.ui.time_to_display'; } diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index 9dc6cb929f..d998c53697 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -91,7 +91,8 @@ class SentryTracer extends ISentrySpan { } @override - Future finish({SpanStatus? status, DateTime? endTimestamp}) async { + Future finish( + {SpanStatus? status, DateTime? endTimestamp, Hint? hint}) async { final commonEndTimestamp = endTimestamp ?? _hub.options.clock(); _autoFinishAfterTimer?.cancel(); _finishStatus = SentryTracerFinishStatus.finishing(status); @@ -135,7 +136,7 @@ class SentryTracer extends ISentrySpan { if (finish is Future) { await finish; } - await _rootSpan.finish(endTimestamp: _rootEndTimestamp); + await _rootSpan.finish(endTimestamp: _rootEndTimestamp, hint: hint); // remove from scope await _hub.configureScope((scope) { @@ -159,6 +160,7 @@ class SentryTracer extends ISentrySpan { await _hub.captureTransaction( transaction, traceContext: traceContext(), + hint: hint, ); } finally { profiler?.dispose(); @@ -275,10 +277,15 @@ class SentryTracer extends ISentrySpan { Future _finishedCallback({ DateTime? endTimestamp, + Hint? hint, }) async { final finishStatus = _finishStatus; if (finishStatus.finishing) { - await finish(status: finishStatus.status, endTimestamp: endTimestamp); + await finish( + status: finishStatus.status, + endTimestamp: endTimestamp, + hint: hint, + ); } } @@ -371,17 +378,12 @@ class SentryTracer extends ISentrySpan { return _sentryTraceContextHeader; } - SentryUser? user; - _hub.configureScope((scope) => user = scope.user); - _sentryTraceContextHeader = SentryTraceContextHeader( _rootSpan.context.traceId, _hub.options.parsedDsn.publicKey, release: _hub.options.release, environment: _hub.options.environment, userId: null, // because of PII not sending it for now - // ignore: deprecated_member_use_from_same_package - userSegment: user?.segment, transaction: _isHighQualityTransactionName(transactionNameSource) ? name : null, sampleRate: _sampleRateToString(_rootSpan.samplingDecision?.sampleRate), diff --git a/dart/lib/src/sentry_traces_sampler.dart b/dart/lib/src/sentry_traces_sampler.dart index f668ad460f..1b4634aee5 100644 --- a/dart/lib/src/sentry_traces_sampler.dart +++ b/dart/lib/src/sentry_traces_sampler.dart @@ -6,8 +6,6 @@ import '../sentry.dart'; @internal class SentryTracesSampler { - static const _defaultSampleRate = 1.0; - final SentryOptions _options; final Random _random; @@ -55,13 +53,8 @@ class SentryTracesSampler { } double? optionsRate = _options.tracesSampleRate; - double? defaultRate = - // ignore: deprecated_member_use_from_same_package - _options.enableTracing == true ? _defaultSampleRate : null; - double? optionsOrDefaultRate = optionsRate ?? defaultRate; - - if (optionsOrDefaultRate != null) { - return _makeSampleDecision(optionsOrDefaultRate); + if (optionsRate != null) { + return _makeSampleDecision(optionsRate); } return SentryTracesSamplingDecision(false); diff --git a/dart/lib/src/sentry_user_feedback.dart b/dart/lib/src/sentry_user_feedback.dart deleted file mode 100644 index 722a0983f1..0000000000 --- a/dart/lib/src/sentry_user_feedback.dart +++ /dev/null @@ -1,69 +0,0 @@ -import 'package:meta/meta.dart'; - -import 'protocol.dart'; -import 'protocol/access_aware_map.dart'; - -@Deprecated('Will be removed in a future version. Use [SentryFeedback] instead') -class SentryUserFeedback { - SentryUserFeedback({ - required this.eventId, - this.name, - this.email, - this.comments, - this.unknown, - }) : assert(eventId != SentryId.empty() && - (name?.isNotEmpty == true || - email?.isNotEmpty == true || - comments?.isNotEmpty == true)); - - factory SentryUserFeedback.fromJson(Map data) { - final json = AccessAwareMap(data); - return SentryUserFeedback( - eventId: SentryId.fromId(json['event_id']), - name: json['name'], - email: json['email'], - comments: json['comments'], - unknown: json.notAccessed(), - ); - } - - /// The eventId of the event to which the user feedback is associated. - final SentryId eventId; - - /// Recommended: The name of the user. - final String? name; - - /// Recommended: The name of the user. - final String? email; - - /// Recommended: Comments of the user about what happened. - final String? comments; - - @internal - final Map? unknown; - - Map toJson() { - return { - ...?unknown, - 'event_id': eventId.toString(), - if (name != null) 'name': name, - if (email != null) 'email': email, - if (comments != null) 'comments': comments, - }; - } - - SentryUserFeedback copyWith({ - SentryId? eventId, - String? name, - String? email, - String? comments, - }) { - return SentryUserFeedback( - eventId: eventId ?? this.eventId, - name: name ?? this.name, - email: email ?? this.email, - comments: comments ?? this.comments, - unknown: unknown, - ); - } -} diff --git a/dart/lib/src/transport/http_transport_request_handler.dart b/dart/lib/src/transport/http_transport_request_handler.dart index e30d71570f..9d1bdd44f4 100644 --- a/dart/lib/src/transport/http_transport_request_handler.dart +++ b/dart/lib/src/transport/http_transport_request_handler.dart @@ -19,7 +19,7 @@ class HttpTransportRequestHandler { HttpTransportRequestHandler(this._options, this._requestUri) : _dsn = _options.parsedDsn, _headers = _buildHeaders( - _options.platformChecker.isWeb, + _options.platform.isWeb, _options.sentryClientName, ) { _credentialBuilder = _CredentialBuilder( diff --git a/dart/lib/src/utils/isolate_utils.dart b/dart/lib/src/utils/isolate_utils.dart index 6575965ff9..0db3332677 100644 --- a/dart/lib/src/utils/isolate_utils.dart +++ b/dart/lib/src/utils/isolate_utils.dart @@ -1,7 +1,6 @@ import 'package:meta/meta.dart'; import '_io_get_isolate_name.dart' - if (dart.library.html) '_web_get_isolate_name.dart' if (dart.library.js_interop) '_web_get_isolate_name.dart' as isolate_getter; @internal diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index bbabb908ac..6fdbe313c2 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -6,10 +6,10 @@ /// tool used to submit events to Sentry.io. /// /// This library contains Sentry.io SDK constants used by this package. -library version; +library; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.14.0'; +const String sdkVersion = '9.0.0-alpha.1'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 2ade1f9eb3..a9c3ea48f9 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 8.14.0 +version: 9.0.0-alpha.1 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. @@ -9,7 +9,7 @@ issue_tracker: https://github.com/getsentry/sentry-dart/issues documentation: https://docs.sentry.io/platforms/dart/ environment: - sdk: '>=2.17.0 <4.0.0' + sdk: '>=3.5.0 <4.0.0' platforms: android: @@ -25,6 +25,7 @@ dependencies: stack_trace: ^1.10.0 uuid: '>=3.0.0 <5.0.0' collection: ^1.16.0 + web: ^1.1.0 dev_dependencies: build_runner: ^2.3.0 diff --git a/dart/test/event_processor/enricher/io_enricher_test.dart b/dart/test/event_processor/enricher/io_enricher_test.dart index 4cd351476d..38bb60e3e1 100644 --- a/dart/test/event_processor/enricher/io_enricher_test.dart +++ b/dart/test/event_processor/enricher/io_enricher_test.dart @@ -1,14 +1,14 @@ @TestOn('vm') -library dart_test; +library; import 'dart:io'; import 'package:sentry/sentry.dart'; import 'package:sentry/src/event_processor/enricher/io_enricher_event_processor.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:test/test.dart'; import '../../mocks.dart'; -import '../../mocks/mock_platform_checker.dart'; import '../../test_utils.dart'; void main() { @@ -255,8 +255,9 @@ class Fixture { bool hasNativeIntegration = false, bool includePii = false, }) { - final options = defaultTestOptions( - MockPlatformChecker(hasNativeIntegration: hasNativeIntegration)) + final options = defaultTestOptions() + ..platform = + hasNativeIntegration ? MockPlatform.iOS() : MockPlatform.fuchsia() ..sendDefaultPii = includePii; return IoEnricherEventProcessor(options); diff --git a/dart/test/event_processor/enricher/io_platform_memory_test.dart b/dart/test/event_processor/enricher/io_platform_memory_test.dart index ce2c8474f4..4ba623db99 100644 --- a/dart/test/event_processor/enricher/io_platform_memory_test.dart +++ b/dart/test/event_processor/enricher/io_platform_memory_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dart_test; +library; import 'dart:io'; diff --git a/dart/test/event_processor/enricher/web_enricher_test.dart b/dart/test/event_processor/enricher/web_enricher_test.dart index 39502fc134..1c3639ec42 100644 --- a/dart/test/event_processor/enricher/web_enricher_test.dart +++ b/dart/test/event_processor/enricher/web_enricher_test.dart @@ -1,14 +1,12 @@ @TestOn('browser') -library dart_test; +library; import 'package:sentry/sentry.dart'; -import 'package:sentry/src/event_processor/enricher/html_enricher_event_processor.dart' - if (dart.library.html) 'package:sentry/src/event_processor/enricher/html_enricher_event_processor.dart' - if (dart.library.js_interop) 'package:sentry/src/event_processor/enricher/web_enricher_event_processor.dart'; +import 'package:sentry/src/event_processor/enricher/web_enricher_event_processor.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:test/test.dart'; import '../../mocks.dart'; -import '../../mocks/mock_platform_checker.dart'; import '../../test_utils.dart'; // can be tested on command line with @@ -202,8 +200,8 @@ void main() { class Fixture { WebEnricherEventProcessor getSut() { - final options = - defaultTestOptions(MockPlatformChecker(hasNativeIntegration: false)); + final options = defaultTestOptions() + ..platform = MockPlatform.fuchsia(); // Does not have native integration return enricherEventProcessor(options) as WebEnricherEventProcessor; } } diff --git a/dart/test/event_processor/exception/io_exception_event_processor_test.dart b/dart/test/event_processor/exception/io_exception_event_processor_test.dart index 9523038638..335f45ab2b 100644 --- a/dart/test/event_processor/exception/io_exception_event_processor_test.dart +++ b/dart/test/event_processor/exception/io_exception_event_processor_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dart_test; +library; import 'dart:io'; diff --git a/dart/test/example_web_compile_test.dart b/dart/test/example_web_compile_test.dart index 1a2a0cf13f..12906e2968 100644 --- a/dart/test/example_web_compile_test.dart +++ b/dart/test/example_web_compile_test.dart @@ -1,19 +1,16 @@ @TestOn('vm') -library dart_test; +library; import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'package:version/version.dart'; import 'package:test/test.dart'; // Tests for the following issue // https://github.com/getsentry/sentry-dart/issues/1893 void main() { - final dartVersion = Version.parse(Platform.version.split(' ')[0]); - final isLegacy = dartVersion < Version.parse('3.3.0'); - final exampleAppDir = isLegacy ? 'example_web_legacy' : 'example_web'; + final exampleAppDir = 'example_web'; final exampleAppWorkingDir = '${Directory.current.path}${Platform.pathSeparator}$exampleAppDir'; group('Compile $exampleAppDir', () { @@ -41,10 +38,9 @@ void main() { reason: 'Could not compile main.dart, likely because of dart:io import.'); expect( - compileResult.stdout, - contains(isLegacy - ? 'Succeeded after ' - : 'build_web_compilers:entrypoint on web/main.dart:Compiled')); + compileResult.stdout, + contains('build_web_compilers:entrypoint on web/main.dart:Compiled'), + ); }, timeout: Timeout(const Duration(minutes: 1)), // double of detault timeout ); @@ -52,6 +48,7 @@ void main() { } /// Runs [command] with command's stdout and stderr being forwrarded to +/// /// test runner's respective streams. It buffers stdout and returns it. /// /// Returns [_CommandResult] with exitCode and stdout as a single sting diff --git a/dart/test/fake_platform_checker.dart b/dart/test/fake_platform_checker.dart deleted file mode 100644 index 928a0be2de..0000000000 --- a/dart/test/fake_platform_checker.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:sentry/src/platform_checker.dart'; - -/// Fake class to be used in unit tests for mocking different environments -class FakePlatformChecker extends PlatformChecker { - FakePlatformChecker.releaseMode() { - _releaseMode = true; - _debugMode = false; - _profileMode = false; - } - - FakePlatformChecker.debugMode() { - _releaseMode = false; - _debugMode = true; - _profileMode = false; - } - - FakePlatformChecker.profileMode() { - _releaseMode = false; - _debugMode = false; - _profileMode = true; - } - - late bool _releaseMode; - late bool _debugMode; - late bool _profileMode; - - @override - bool isReleaseMode() { - return _releaseMode; - } - - @override - bool isDebugMode() { - return _debugMode; - } - - @override - bool isProfileMode() { - return _profileMode; - } -} diff --git a/dart/test/http_client/io_client_provider_test.dart b/dart/test/http_client/io_client_provider_test.dart index 81d05c1540..211c3e3900 100644 --- a/dart/test/http_client/io_client_provider_test.dart +++ b/dart/test/http_client/io_client_provider_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dart_test; +library; import 'dart:io'; diff --git a/dart/test/http_client/tracing_client_test.dart b/dart/test/http_client/tracing_client_test.dart index 4e052dc518..7c34281dfc 100644 --- a/dart/test/http_client/tracing_client_test.dart +++ b/dart/test/http_client/tracing_client_test.dart @@ -177,8 +177,9 @@ void main() { test('set headers from propagationContext when tracing is disabled', () async { - // ignore: deprecated_member_use_from_same_package - fixture._options.enableTracing = false; + fixture._options.tracesSampler = null; + fixture._options.tracesSampleRate = null; + final sut = fixture.getSut( client: fixture.getClient(statusCode: 200, reason: 'OK'), ); diff --git a/dart/test/hub_test.dart b/dart/test/hub_test.dart index 6dbf6f1288..5331aacc5e 100644 --- a/dart/test/hub_test.dart +++ b/dart/test/hub_test.dart @@ -395,6 +395,16 @@ void main() { expect( fixture.client.captureTransactionCalls.first.traceContext, context); }); + + test('captureTransaction hint is passed to client', () async { + final hub = fixture.getSut(); + + var hint = Hint(); + var tr = SentryTransaction(fixture.tracer); + await hub.captureTransaction(tr, hint: hint); + + expect(fixture.client.captureTransactionCalls.first.hint, hint); + }); }); group('Hub profiles', () { diff --git a/dart/test/initialization_test.dart b/dart/test/initialization_test.dart index 42766ac93d..46c0cd35c6 100644 --- a/dart/test/initialization_test.dart +++ b/dart/test/initialization_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dart_test; +library; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; diff --git a/dart/test/load_dart_debug_images_integration_test.dart b/dart/test/load_dart_debug_images_integration_test.dart index 84d478ab08..966dec2e69 100644 --- a/dart/test/load_dart_debug_images_integration_test.dart +++ b/dart/test/load_dart_debug_images_integration_test.dart @@ -1,15 +1,14 @@ @TestOn('vm') -library dart_test; +library; import 'dart:async'; import 'package:sentry/sentry.dart'; import 'package:sentry/src/load_dart_debug_images_integration.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; import 'package:test/test.dart'; -import 'mocks/mock_platform.dart'; -import 'mocks/mock_platform_checker.dart'; import 'test_utils.dart'; void main() { @@ -26,8 +25,7 @@ void main() { setUp(() { fixture = Fixture(); - fixture.options.platformChecker = - MockPlatformChecker(platform: platform); + fixture.options.platform = platform; }); test('adds itself to sdk.integrations', () { @@ -193,9 +191,7 @@ isolate_dso_base: 10000000 } test('debug image is null on unsupported platforms', () async { - final fixture = Fixture() - ..options.platformChecker = - MockPlatformChecker(platform: MockPlatform.linux()); + final fixture = Fixture()..options.platform = MockPlatform.linux(); final event = fixture.newEvent(stackTrace: fixture.parse(''' *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** build_id: 'b680cb890f9e3c12a24b172d050dec73' diff --git a/dart/test/mocks.mocks.dart b/dart/test/mocks.mocks.dart index 58133b794b..50e154087c 100644 --- a/dart/test/mocks.mocks.dart +++ b/dart/test/mocks.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.4 from annotations +// Mocks generated by Mockito 5.4.5 from annotations // in sentry/test/mocks.dart. // Do not manually edit this file. @@ -17,6 +17,7 @@ import 'package:sentry/src/profiling.dart' as _i3; // ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types @@ -24,13 +25,8 @@ import 'package:sentry/src/profiling.dart' as _i3; class _FakeSentryEnvelopeItem_0 extends _i1.SmartFake implements _i2.SentryEnvelopeItem { - _FakeSentryEnvelopeItem_0( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeSentryEnvelopeItem_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } /// A class which mocks [SentryProfilerFactory]. @@ -44,10 +40,8 @@ class MockSentryProfilerFactory extends _i1.Mock @override _i3.SentryProfiler? startProfiler(_i2.SentryTransactionContext? context) => - (super.noSuchMethod(Invocation.method( - #startProfiler, - [context], - )) as _i3.SentryProfiler?); + (super.noSuchMethod(Invocation.method(#startProfiler, [context])) + as _i3.SentryProfiler?); } /// A class which mocks [SentryProfiler]. @@ -60,21 +54,16 @@ class MockSentryProfiler extends _i1.Mock implements _i3.SentryProfiler { @override _i4.Future<_i3.SentryProfileInfo?> finishFor( - _i2.SentryTransaction? transaction) => + _i2.SentryTransaction? transaction, + ) => (super.noSuchMethod( - Invocation.method( - #finishFor, - [transaction], - ), + Invocation.method(#finishFor, [transaction]), returnValue: _i4.Future<_i3.SentryProfileInfo?>.value(), ) as _i4.Future<_i3.SentryProfileInfo?>); @override void dispose() => super.noSuchMethod( - Invocation.method( - #dispose, - [], - ), + Invocation.method(#dispose, []), returnValueForMissingStub: null, ); } @@ -89,16 +78,10 @@ class MockSentryProfileInfo extends _i1.Mock implements _i3.SentryProfileInfo { @override _i2.SentryEnvelopeItem asEnvelopeItem() => (super.noSuchMethod( - Invocation.method( - #asEnvelopeItem, - [], - ), + Invocation.method(#asEnvelopeItem, []), returnValue: _FakeSentryEnvelopeItem_0( this, - Invocation.method( - #asEnvelopeItem, - [], - ), + Invocation.method(#asEnvelopeItem, []), ), ) as _i2.SentryEnvelopeItem); } diff --git a/dart/test/mocks/mock_hub.dart b/dart/test/mocks/mock_hub.dart index 62db6c13a4..2ba6a43774 100644 --- a/dart/test/mocks/mock_hub.dart +++ b/dart/test/mocks/mock_hub.dart @@ -13,7 +13,6 @@ class MockHub with NoSuchMethodProvider implements Hub { List bindClientCalls = []; // ignore: deprecated_member_use_from_same_package - List userFeedbackCalls = []; List captureTransactionCalls = []; int closeCalls = 0; bool _isEnabled = true; @@ -112,18 +111,13 @@ class MockHub with NoSuchMethodProvider implements Hub { Future captureTransaction( SentryTransaction transaction, { SentryTraceContextHeader? traceContext, + Hint? hint, }) async { captureTransactionCalls - .add(CaptureTransactionCall(transaction, traceContext)); + .add(CaptureTransactionCall(transaction, traceContext, hint)); return transaction.eventId; } - @override - // ignore: deprecated_member_use_from_same_package - Future captureUserFeedback(SentryUserFeedback userFeedback) async { - userFeedbackCalls.add(userFeedback); - } - @override ISentrySpan? getSpan() { getSpanCalls++; diff --git a/dart/test/mocks/mock_platform.dart b/dart/test/mocks/mock_platform.dart deleted file mode 100644 index 21dc234b09..0000000000 --- a/dart/test/mocks/mock_platform.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'dart:typed_data'; - -import 'package:sentry/src/platform/platform.dart'; - -import 'no_such_method_provider.dart'; - -class MockPlatform extends Platform with NoSuchMethodProvider { - MockPlatform({String? os, Endian? endian}) - : operatingSystem = os ?? '', - endian = endian ?? Endian.host; - - factory MockPlatform.android() { - return MockPlatform(os: 'android'); - } - - factory MockPlatform.iOS() { - return MockPlatform(os: 'ios'); - } - - factory MockPlatform.macOS() { - return MockPlatform(os: 'macos'); - } - - factory MockPlatform.linux() { - return MockPlatform(os: 'linux'); - } - - factory MockPlatform.windows() { - return MockPlatform(os: 'windows'); - } - - @override - final String operatingSystem; - - @override - final Endian endian; - - @override - String toString() => operatingSystem; -} diff --git a/dart/test/mocks/mock_platform_checker.dart b/dart/test/mocks/mock_platform_checker.dart deleted file mode 100644 index efb58d6c7a..0000000000 --- a/dart/test/mocks/mock_platform_checker.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:sentry/src/platform/platform.dart'; -import 'package:sentry/src/platform_checker.dart'; - -import 'no_such_method_provider.dart'; - -class MockPlatformChecker extends PlatformChecker with NoSuchMethodProvider { - MockPlatformChecker({ - this.isDebug = false, - this.isProfile = false, - this.isRelease = false, - this.isWebValue = false, - this.hasNativeIntegration = false, - Platform? platform, - }) : _platform = platform; - - final Platform? _platform; - - final bool isDebug; - final bool isProfile; - final bool isRelease; - final bool isWebValue; - - @override - bool hasNativeIntegration = false; - - @override - bool isDebugMode() => isDebug; - - @override - bool isProfileMode() => isProfile; - - @override - bool isReleaseMode() => isRelease; - - @override - bool get isWeb => isWebValue; - - @override - Platform get platform => _platform ?? super.platform; -} diff --git a/dart/test/mocks/mock_runtime_checker.dart b/dart/test/mocks/mock_runtime_checker.dart new file mode 100644 index 0000000000..c7ea74b730 --- /dev/null +++ b/dart/test/mocks/mock_runtime_checker.dart @@ -0,0 +1,25 @@ +import 'package:sentry/src/runtime_checker.dart'; + +import 'no_such_method_provider.dart'; + +class MockRuntimeChecker extends RuntimeChecker with NoSuchMethodProvider { + MockRuntimeChecker({ + this.isDebug = false, + this.isProfile = false, + this.isRelease = false, + bool isRootZone = true, + }) : super(isRootZone: isRootZone); + + final bool isDebug; + final bool isProfile; + final bool isRelease; + + @override + bool isDebugMode() => isDebug; + + @override + bool isProfileMode() => isProfile; + + @override + bool isReleaseMode() => isRelease; +} diff --git a/dart/test/mocks/mock_sentry_client.dart b/dart/test/mocks/mock_sentry_client.dart index 7a79b31f7c..6138eb5295 100644 --- a/dart/test/mocks/mock_sentry_client.dart +++ b/dart/test/mocks/mock_sentry_client.dart @@ -9,8 +9,6 @@ class MockSentryClient with NoSuchMethodProvider implements SentryClient { List captureEnvelopeCalls = []; List captureTransactionCalls = []; - // ignore: deprecated_member_use_from_same_package - List userFeedbackCalls = []; List captureFeedbackCalls = []; int closeCalls = 0; @@ -72,12 +70,6 @@ class MockSentryClient with NoSuchMethodProvider implements SentryClient { return envelope.header.eventId ?? SentryId.newId(); } - @override - // ignore: deprecated_member_use_from_same_package - Future captureUserFeedback(SentryUserFeedback userFeedback) async { - userFeedbackCalls.add(userFeedback); - } - @override Future captureFeedback( SentryFeedback feedback, { @@ -102,9 +94,10 @@ class MockSentryClient with NoSuchMethodProvider implements SentryClient { SentryTransaction transaction, { Scope? scope, SentryTraceContextHeader? traceContext, + Hint? hint, }) async { captureTransactionCalls - .add(CaptureTransactionCall(transaction, traceContext)); + .add(CaptureTransactionCall(transaction, traceContext, hint)); return transaction.eventId; } } @@ -176,6 +169,7 @@ class CaptureEnvelopeCall { class CaptureTransactionCall { final SentryTransaction transaction; final SentryTraceContextHeader? traceContext; + final Hint? hint; - CaptureTransactionCall(this.transaction, this.traceContext); + CaptureTransactionCall(this.transaction, this.traceContext, this.hint); } diff --git a/dart/test/protocol/sentry_baggage_header_test.dart b/dart/test/protocol/sentry_baggage_header_test.dart index 6d75d6dd15..ef792877f9 100644 --- a/dart/test/protocol/sentry_baggage_header_test.dart +++ b/dart/test/protocol/sentry_baggage_header_test.dart @@ -17,8 +17,6 @@ void main() { baggage.setRelease('release'); baggage.setEnvironment('environment'); baggage.setUserId('userId'); - // ignore: deprecated_member_use_from_same_package - baggage.setUserSegment('userSegment'); baggage.setTransaction('transaction'); baggage.setSampleRate('1.0'); baggage.setSampleRand('0.4'); @@ -35,7 +33,6 @@ void main() { 'sentry-release=release,' 'sentry-environment=environment,' 'sentry-user_id=userId,' - 'sentry-user_segment=userSegment,' 'sentry-transaction=transaction,' 'sentry-sample_rate=1.0,' 'sentry-sample_rand=0.4,' diff --git a/dart/test/protocol/sentry_user_test.dart b/dart/test/protocol/sentry_user_test.dart index dbc6e6cd87..7e12ae6c3e 100644 --- a/dart/test/protocol/sentry_user_test.dart +++ b/dart/test/protocol/sentry_user_test.dart @@ -11,7 +11,6 @@ void main() { email: 'email', ipAddress: 'ipAddress', data: {'key': 'value'}, - segment: 'seg', unknown: testUnknown, ); @@ -21,7 +20,6 @@ void main() { 'email': 'email', 'ip_address': 'ipAddress', 'data': {'key': 'value'}, - 'segment': 'seg', }; sentryUserJson.addAll(testUnknown); @@ -56,7 +54,6 @@ void main() { expect(json.containsKey('email'), false); expect(json.containsKey('ip_address'), false); expect(json.containsKey('extras'), false); - expect(json.containsKey('segment'), false); data = SentryUser(ipAddress: 'ip'); @@ -67,7 +64,6 @@ void main() { expect(json.containsKey('email'), false); expect(json.containsKey('ip_address'), true); expect(json.containsKey('extras'), false); - expect(json.containsKey('segment'), false); }); }); @@ -89,7 +85,6 @@ void main() { email: 'email1', ipAddress: 'ipAddress1', data: {'key1': 'value1'}, - segment: 'seg1', ); expect('id1', copy.id); @@ -97,8 +92,6 @@ void main() { expect('email1', copy.email); expect('ipAddress1', copy.ipAddress); expect({'key1': 'value1'}, copy.data); - // ignore: deprecated_member_use_from_same_package - expect('seg1', copy.segment); }); }); } diff --git a/dart/test/sentry_attachment_io_test.dart b/dart/test/sentry_attachment_io_test.dart index 29a0076bfe..1dd1850f41 100644 --- a/dart/test/sentry_attachment_io_test.dart +++ b/dart/test/sentry_attachment_io_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dart_test; +library; import 'dart:io'; diff --git a/dart/test/sentry_browser_test.dart b/dart/test/sentry_browser_test.dart index eaccfa1d03..cb83f510c9 100644 --- a/dart/test/sentry_browser_test.dart +++ b/dart/test/sentry_browser_test.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @TestOn('browser') -library dart_test; +library; import 'package:test/test.dart'; diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index ede2330686..d605a2b86b 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -6,6 +6,7 @@ import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry/src/client_reports/discard_reason.dart'; import 'package:sentry/src/client_reports/noop_client_report_recorder.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:sentry/src/sentry_item_type.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; import 'package:sentry/src/sentry_tracer.dart'; @@ -19,8 +20,6 @@ import 'package:test/test.dart'; import 'mocks.dart'; import 'mocks/mock_client_report_recorder.dart'; import 'mocks/mock_hub.dart'; -import 'mocks/mock_platform.dart'; -import 'mocks/mock_platform_checker.dart'; import 'mocks/mock_transport.dart'; import 'test_utils.dart'; @@ -1404,7 +1403,8 @@ void main() { test('thrown error is handled', () async { fixture.options.automatedTestMode = false; final exception = Exception("before send exception"); - final beforeSendTransactionCallback = (SentryTransaction event) { + final beforeSendTransactionCallback = + (SentryTransaction event, Hint hint) { throw exception; }; @@ -1803,7 +1803,7 @@ void main() { fixture.tracer.startChild('child2'); fixture.tracer.startChild('child3'); - fixture.options.beforeSendTransaction = (transaction) { + fixture.options.beforeSendTransaction = (transaction, hint) { if (transaction.tracer == fixture.tracer) { return null; } @@ -1830,7 +1830,7 @@ void main() { fixture.tracer.startChild('child2'); fixture.tracer.startChild('child3'); - fixture.options.beforeSendTransaction = (transaction) { + fixture.options.beforeSendTransaction = (transaction, hint) { if (transaction.tracer == fixture.tracer) { transaction.spans .removeWhere((element) => element.context.operation == 'child2'); @@ -1893,22 +1893,6 @@ void main() { expect( fixture.recorder.discardedEvents.first.category, DataCategory.error); }); - - test('user feedback envelope contains dsn', () async { - final client = fixture.getSut(); - final event = SentryEvent(); - // ignore: deprecated_member_use_from_same_package - final feedback = SentryUserFeedback( - eventId: event.eventId, - name: 'test', - ); - // ignore: deprecated_member_use_from_same_package - await client.captureUserFeedback(feedback); - - final capturedEnvelope = (fixture.transport).envelopes.first; - - expect(capturedEnvelope.header.dsn, fixture.options.dsn); - }); }); group('Spotlight', () { @@ -1921,9 +1905,7 @@ void main() { test( 'Spotlight enabled should not set transport to SpotlightHttpTransport on iOS', () async { - fixture.options.platformChecker = MockPlatformChecker( - platform: MockPlatform.iOS(), - ); + fixture.options.platform = MockPlatform.iOS(); fixture.options.spotlight = Spotlight(enabled: true); fixture.getSut(); @@ -1933,9 +1915,7 @@ void main() { test( 'Spotlight enabled should not set transport to SpotlightHttpTransport on macOS', () async { - fixture.options.platformChecker = MockPlatformChecker( - platform: MockPlatform.macOS(), - ); + fixture.options.platform = MockPlatform.macOS(); fixture.options.spotlight = Spotlight(enabled: true); fixture.getSut(); @@ -1945,9 +1925,7 @@ void main() { test( 'Spotlight enabled should not set transport to SpotlightHttpTransport on Android', () async { - fixture.options.platformChecker = MockPlatformChecker( - platform: MockPlatform.android(), - ); + fixture.options.platform = MockPlatform.android(); fixture.options.spotlight = Spotlight(enabled: true); fixture.getSut(); @@ -1957,7 +1935,7 @@ void main() { test( 'Spotlight enabled should set transport to SpotlightHttpTransport on Web', () async { - fixture.options.platformChecker = MockPlatformChecker(isWebValue: true); + fixture.options.platform = MockPlatform(isWeb: true); fixture.options.spotlight = Spotlight(enabled: true); fixture.getSut(); @@ -1967,8 +1945,7 @@ void main() { test( 'Spotlight enabled should set transport to SpotlightHttpTransport on Linux', () async { - fixture.options.platformChecker = - MockPlatformChecker(platform: MockPlatform.linux()); + fixture.options.platform = MockPlatform.linux(); fixture.options.spotlight = Spotlight(enabled: true); fixture.getSut(); @@ -1978,8 +1955,7 @@ void main() { test( 'Spotlight enabled should set transport to SpotlightHttpTransport on Windows', () async { - fixture.options.platformChecker = - MockPlatformChecker(platform: MockPlatform.windows()); + fixture.options.platform = MockPlatform.windows(); fixture.options.spotlight = Spotlight(enabled: true); fixture.getSut(); @@ -2081,6 +2057,33 @@ void main() { SentryAttachment.typeAttachmentDefault); }); + test('captureTransaction hint passed to beforeSendTransaction', () async { + final sut = fixture.getSut(); + + final hint = Hint(); + final transaction = SentryTransaction(fixture.tracer); + + fixture.options.beforeSendTransaction = (bsTransaction, bsHint) async { + expect(hint, bsHint); + return bsTransaction; + }; + + await sut.captureTransaction(transaction, hint: hint); + }); + + test('captureTransaction hint passed to event processors', () async { + final hint = Hint(); + + final eventProcessor = FunctionEventProcessor((event, epHint) { + expect(epHint, hint); + return event; + }); + final sut = fixture.getSut(eventProcessor: eventProcessor); + + final transaction = SentryTransaction(fixture.tracer); + await sut.captureTransaction(transaction, hint: hint); + }); + test('captureEvent adds screenshot from hint', () async { final client = fixture.getSut(); final screenshot = @@ -2233,6 +2236,7 @@ Future asyncBeforeSendFeedbackCallbackDropEvent( SentryTransaction? beforeSendTransactionCallbackDropEvent( SentryTransaction event, + Hint hint, ) => null; @@ -2245,7 +2249,9 @@ Future asyncBeforeSendCallbackDropEvent( } Future asyncBeforeSendTransactionCallbackDropEvent( - SentryEvent event) async { + SentryEvent event, + Hint hint, +) async { await Future.delayed(Duration(milliseconds: 200)); return null; } @@ -2267,7 +2273,9 @@ SentryEvent? beforeSendCallback(SentryEvent event, Hint hint) { } SentryTransaction? beforeSendTransactionCallback( - SentryTransaction transaction) { + SentryTransaction transaction, + Hint hint, +) { return transaction ..tags!.addAll({'theme': 'material'}) // ignore: deprecated_member_use_from_same_package @@ -2281,8 +2289,7 @@ class Fixture { final recorder = MockClientReportRecorder(); final transport = MockTransport(); - final options = - defaultTestOptions(MockPlatformChecker(platform: MockPlatform.iOS())); + final options = defaultTestOptions()..platform = MockPlatform.iOS(); late SentryTransactionContext _context; late SentryTracer tracer; diff --git a/dart/test/sentry_envelope_item_test.dart b/dart/test/sentry_envelope_item_test.dart index aac20a7fb5..9e63104a31 100644 --- a/dart/test/sentry_envelope_item_test.dart +++ b/dart/test/sentry_envelope_item_test.dart @@ -95,26 +95,5 @@ void main() { expect(sut.header.type, SentryItemType.clientReport); expect(actualData, expectedData); }); - - test('fromUserFeedback', () async { - // ignore: deprecated_member_use_from_same_package - final userFeedback = SentryUserFeedback( - eventId: SentryId.newId(), - name: 'name', - comments: 'comments', - email: 'email'); - // ignore: deprecated_member_use_from_same_package - final sut = SentryEnvelopeItem.fromUserFeedback(userFeedback); - - final expectedData = utf8.encode(jsonEncode( - userFeedback.toJson(), - toEncodable: jsonSerializationFallback, - )); - final actualData = await sut.dataFactory(); - - expect(sut.header.contentType, 'application/json'); - expect(sut.header.type, SentryItemType.userFeedback); - expect(actualData, expectedData); - }); }); } diff --git a/dart/test/sentry_envelope_test.dart b/dart/test/sentry_envelope_test.dart index e8087527e7..9f60ab4bc7 100644 --- a/dart/test/sentry_envelope_test.dart +++ b/dart/test/sentry_envelope_test.dart @@ -135,36 +135,6 @@ void main() { expect(actualItem, expectedItem); }); - test('fromUserFeedback', () async { - final eventId = SentryId.newId(); - // ignore: deprecated_member_use_from_same_package - final userFeedback = SentryUserFeedback( - eventId: eventId, name: 'name', email: 'email', comments: 'comments'); - final sdkVersion = - SdkVersion(name: 'fixture-name', version: 'fixture-version'); - // ignore: deprecated_member_use_from_same_package - final sut = SentryEnvelope.fromUserFeedback( - userFeedback, - sdkVersion, - dsn: fakeDsn, - ); - - final expectedEnvelopeItem = - // ignore: deprecated_member_use_from_same_package - SentryEnvelopeItem.fromUserFeedback(userFeedback); - - expect(sut.header.eventId, eventId); - expect(sut.header.sdkVersion, sdkVersion); - expect(sut.header.dsn, fakeDsn); - expect(sut.items[0].header.contentType, - expectedEnvelopeItem.header.contentType); - expect(sut.items[0].header.type, expectedEnvelopeItem.header.type); - - final actualItem = await sut.items[0].dataFactory(); - final expectedItem = await expectedEnvelopeItem.dataFactory(); - expect(actualItem, expectedItem); - }); - test('max attachment size', () async { final attachment = SentryAttachment.fromLoader( loader: () => Uint8List.fromList([1, 2, 3, 4]), diff --git a/dart/test/sentry_envelope_vm_test.dart b/dart/test/sentry_envelope_vm_test.dart index f4a22881cc..96da255234 100644 --- a/dart/test/sentry_envelope_vm_test.dart +++ b/dart/test/sentry_envelope_vm_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dart_test; +library; import 'dart:convert'; import 'dart:io'; diff --git a/dart/test/sentry_event_test.dart b/dart/test/sentry_event_test.dart index fe9d3b4d48..ce70623ff0 100644 --- a/dart/test/sentry_event_test.dart +++ b/dart/test/sentry_event_test.dart @@ -4,6 +4,7 @@ import 'package:collection/collection.dart'; import 'package:sentry/sentry.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:sentry/src/version.dart'; import 'package:test/test.dart'; @@ -130,12 +131,12 @@ void main() { ); }); test('$SdkVersion serializes', () { - var platformChecker = PlatformChecker(); + final platform = MockPlatform(); final event = SentryEvent( eventId: SentryId.empty(), timestamp: DateTime.utc(2019), - platform: sdkPlatform(platformChecker.isWeb), + platform: sdkPlatform(platform.isWeb), sdk: SdkVersion( name: 'sentry.dart.flutter', version: '4.3.2', @@ -146,7 +147,7 @@ void main() { ), ); expect(event.toJson(), { - 'platform': platformChecker.isWeb ? 'javascript' : 'other', + 'platform': platform.isWeb ? 'javascript' : 'other', 'event_id': '00000000000000000000000000000000', 'timestamp': '2019-01-01T00:00:00.000Z', 'sdk': { @@ -160,7 +161,7 @@ void main() { }); }); test('serializes to JSON', () { - var platformChecker = PlatformChecker(); + final platform = MockPlatform(); final timestamp = DateTime.utc(2019); final user = SentryUser( @@ -190,7 +191,7 @@ void main() { SentryEvent( eventId: SentryId.empty(), timestamp: timestamp, - platform: sdkPlatform(platformChecker.isWeb), + platform: sdkPlatform(platform.isWeb), message: SentryMessage( 'test-message 1 2', template: 'test-message %d %d', @@ -239,7 +240,7 @@ void main() { unknown: testUnknown) .toJson(), { - 'platform': platformChecker.isWeb ? 'javascript' : 'other', + 'platform': platform.isWeb ? 'javascript' : 'other', 'event_id': '00000000000000000000000000000000', 'timestamp': '2019-01-01T00:00:00.000Z', 'message': { diff --git a/dart/test/sentry_exception_factory_test.dart b/dart/test/sentry_exception_factory_test.dart index 643414ab67..ad6df2a724 100644 --- a/dart/test/sentry_exception_factory_test.dart +++ b/dart/test/sentry_exception_factory_test.dart @@ -279,7 +279,7 @@ ${StackTraceErrorStackTrace()}'''; } } -class StackTraceErrorStackTrace extends StackTrace { +class StackTraceErrorStackTrace implements StackTrace { @override String toString() { return ''' @@ -318,7 +318,7 @@ ${SentryStackTrace()}'''; } } -class SentryStackTrace extends StackTrace { +class SentryStackTrace implements StackTrace { @override String toString() { return ''' diff --git a/dart/test/sentry_io_client_test.dart b/dart/test/sentry_io_client_test.dart index 9ffe1f319c..a775073b7c 100644 --- a/dart/test/sentry_io_client_test.dart +++ b/dart/test/sentry_io_client_test.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @TestOn('vm') -library dart_test; +library; import 'dart:io'; diff --git a/dart/test/sentry_isolate_extension_test.dart b/dart/test/sentry_isolate_extension_test.dart index 89c6a0fe4b..8cffea9c1c 100644 --- a/dart/test/sentry_isolate_extension_test.dart +++ b/dart/test/sentry_isolate_extension_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dart_test; +library; import 'dart:isolate'; diff --git a/dart/test/sentry_isolate_test.dart b/dart/test/sentry_isolate_test.dart index 07347d5585..597c1de795 100644 --- a/dart/test/sentry_isolate_test.dart +++ b/dart/test/sentry_isolate_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dart_test; +library; import 'package:sentry/src/hub.dart'; import 'package:sentry/src/protocol/sentry_level.dart'; diff --git a/dart/test/sentry_options_test.dart b/dart/test/sentry_options_test.dart index 958594b818..2179f2e5bd 100644 --- a/dart/test/sentry_options_test.dart +++ b/dart/test/sentry_options_test.dart @@ -35,12 +35,9 @@ void main() { test('SentryLogger sets a diagnostic logger', () { final options = defaultTestOptions(); - // ignore: deprecated_member_use_from_same_package expect(options.logger, noOpLogger); - // ignore: deprecated_member_use_from_same_package - options.logger = dartLogger; + options.debug = true; - // ignore: deprecated_member_use_from_same_package expect(options.logger, isNot(noOpLogger)); }); @@ -101,7 +98,7 @@ void main() { final options = defaultTestOptions(); expect(options.sentryClientName, - '${sdkName(options.platformChecker.isWeb)}/$sdkVersion'); + '${sdkName(options.platform.isWeb)}/$sdkVersion'); }); test('SentryOptions has default idleTimeout', () { @@ -110,26 +107,6 @@ void main() { expect(options.idleTimeout?.inSeconds, Duration(seconds: 3).inSeconds); }); - test('when enableTracing is set to true tracing is considered enabled', () { - final options = SentryOptions.empty(); - // ignore: deprecated_member_use_from_same_package - options.enableTracing = true; - - expect(options.isTracingEnabled(), true); - }); - - test('when enableTracing is set to false tracing is considered disabled', () { - final options = SentryOptions.empty(); - // ignore: deprecated_member_use_from_same_package - options.enableTracing = false; - options.tracesSampleRate = 1.0; - options.tracesSampler = (_) { - return 1.0; - }; - - expect(options.isTracingEnabled(), false); - }); - test('Spotlight is disabled by default', () { final options = defaultTestOptions(); diff --git a/dart/test/sentry_run_zoned_guarded_test.dart b/dart/test/sentry_run_zoned_guarded_test.dart index 86bc6741c1..1fd06310dd 100644 --- a/dart/test/sentry_run_zoned_guarded_test.dart +++ b/dart/test/sentry_run_zoned_guarded_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dart_test; +library; import 'dart:async'; diff --git a/dart/test/sentry_span_test.dart b/dart/test/sentry_span_test.dart index 9e77f0ba81..7b3486baea 100644 --- a/dart/test/sentry_span_test.dart +++ b/dart/test/sentry_span_test.dart @@ -235,12 +235,15 @@ void main() { test('callback called on finish', () async { var numberOfCallbackCalls = 0; - final sut = - fixture.getSut(finishedCallback: ({DateTime? endTimestamp}) async { + final passedHint = Hint(); + + final sut = fixture.getSut( + finishedCallback: ({DateTime? endTimestamp, Hint? hint}) async { + expect(passedHint, hint); numberOfCallbackCalls += 1; }); - await sut.finish(); + await sut.finish(hint: passedHint); expect(numberOfCallbackCalls, 1); }); diff --git a/dart/test/sentry_test.dart b/dart/test/sentry_test.dart index 0ebae3b726..6d519b4948 100644 --- a/dart/test/sentry_test.dart +++ b/dart/test/sentry_test.dart @@ -5,10 +5,9 @@ import 'package:sentry/src/dart_exception_type_identifier.dart'; import 'package:sentry/src/event_processor/deduplication_event_processor.dart'; import 'package:test/test.dart'; -import 'fake_platform_checker.dart'; import 'mocks.dart'; import 'mocks/mock_integration.dart'; -import 'mocks/mock_platform_checker.dart'; +import 'mocks/mock_runtime_checker.dart'; import 'mocks/mock_sentry_client.dart'; import 'test_utils.dart'; @@ -143,6 +142,14 @@ void main() { expect(client.captureTransactionCalls.length, 1); }); + test('should start transaction with hint', () async { + final tr = Sentry.startTransactionWithContext( + SentryTransactionContext('name', 'operation')); + await tr.finish(); + + expect(client.captureTransactionCalls.length, 1); + }); + test('should return span if bound to the scope', () async { final tr = Sentry.startTransaction('name', 'op', bindToScope: true); @@ -364,7 +371,7 @@ void main() { test('should set options.debug to true when in debug mode', () async { final options = defaultTestOptions(); - options.platformChecker = MockPlatformChecker(isDebug: true); + options.runtimeChecker = MockRuntimeChecker(isDebug: true); expect(options.debug, isFalse); await Sentry.init( @@ -378,7 +385,7 @@ void main() { test('should respect user options.debug when in debug mode', () async { final options = defaultTestOptions(); - options.platformChecker = MockPlatformChecker(isDebug: true); + options.runtimeChecker = MockRuntimeChecker(isDebug: true); expect(options.debug, isFalse); await Sentry.init( @@ -394,7 +401,7 @@ void main() { test('should leave options.debug unchanged when not in debug mode', () async { final options = defaultTestOptions(); - options.platformChecker = MockPlatformChecker(isDebug: false); + options.runtimeChecker = MockRuntimeChecker(isDebug: false); expect(options.debug, isFalse); await Sentry.init( @@ -435,7 +442,8 @@ void main() { }); test('options.environment debug', () async { - final sentryOptions = defaultTestOptions(FakePlatformChecker.debugMode()); + final sentryOptions = + defaultTestOptions(checker: MockRuntimeChecker(isDebug: true)); await Sentry.init( (options) { options.dsn = fakeDsn; @@ -447,7 +455,8 @@ void main() { }); test('options.environment profile', () async { - final sentryOptions = defaultTestOptions(FakePlatformChecker.profileMode()); + final sentryOptions = + defaultTestOptions(checker: MockRuntimeChecker(isProfile: true)); await Sentry.init( (options) { @@ -460,7 +469,8 @@ void main() { }); test('options.environment production (defaultEnvironment)', () async { - final sentryOptions = defaultTestOptions(FakePlatformChecker.releaseMode()); + final sentryOptions = + defaultTestOptions(checker: MockRuntimeChecker(isRelease: true)); await Sentry.init( (options) { options.dsn = fakeDsn; @@ -472,24 +482,22 @@ void main() { }); test('options.logger is set by setting the debug flag', () async { - final sentryOptions = defaultTestOptions(FakePlatformChecker.debugMode()); + final sentryOptions = + defaultTestOptions(checker: MockRuntimeChecker(isDebug: true)); await Sentry.init( (options) { options.dsn = fakeDsn; options.debug = true; - // ignore: deprecated_member_use_from_same_package expect(options.logger, isNot(noOpLogger)); options.debug = false; - // ignore: deprecated_member_use_from_same_package expect(options.logger, noOpLogger); }, options: sentryOptions, ); - // ignore: deprecated_member_use_from_same_package - expect(sentryOptions.logger, isNot(dartLogger)); + expect(sentryOptions.logger, noOpLogger); }); group('Sentry init optionsConfiguration', () { @@ -500,9 +508,9 @@ void main() { }); test('throw is handled and logged', () async { - // Use release mode in platform checker to avoid additional log + // Use release mode in runtime checker to avoid additional log final sentryOptions = - defaultTestOptions(FakePlatformChecker.releaseMode()) + defaultTestOptions(checker: MockRuntimeChecker(isRelease: true)) ..automatedTestMode = false ..debug = true ..logger = fixture.mockLogger; diff --git a/dart/test/sentry_trace_context_header_test.dart b/dart/test/sentry_trace_context_header_test.dart index 04b2526c34..eb97f87913 100644 --- a/dart/test/sentry_trace_context_header_test.dart +++ b/dart/test/sentry_trace_context_header_test.dart @@ -14,7 +14,6 @@ void main() { release: 'release', environment: 'environment', userId: 'user_id', - userSegment: 'user_segment', transaction: 'transaction', sampleRate: '1.0', sampled: 'false', @@ -28,7 +27,6 @@ void main() { 'release': 'release', 'environment': 'environment', 'user_id': 'user_id', - 'user_segment': 'user_segment', 'transaction': 'transaction', 'sample_rate': '1.0', 'sampled': 'false', @@ -42,8 +40,6 @@ void main() { expect(context.release, 'release'); expect(context.environment, 'environment'); expect(context.userId, 'user_id'); - // ignore: deprecated_member_use_from_same_package - expect(context.userSegment, 'user_segment'); expect(context.transaction, 'transaction'); expect(context.sampleRate, '1.0'); expect(context.sampled, 'false'); @@ -66,7 +62,6 @@ void main() { 'sentry-release=release,' 'sentry-environment=environment,' 'sentry-user_id=user_id,' - 'sentry-user_segment=user_segment,' 'sentry-transaction=transaction,' 'sentry-sample_rate=1.0,' 'sentry-sampled=false,' diff --git a/dart/test/sentry_tracer_test.dart b/dart/test/sentry_tracer_test.dart index d5dde5ae98..86f6f02ccb 100644 --- a/dart/test/sentry_tracer_test.dart +++ b/dart/test/sentry_tracer_test.dart @@ -468,6 +468,16 @@ void main() { expect(sut.measurements.containsKey("test"), true); expect(sut.measurements["test"]!.value, 1); }); + + test('hint passed to hub', () async { + final hint = Hint(); + + final sut = fixture.getSut(); + + await sut.finish(hint: hint); + + expect(fixture.hub.captureTransactionCalls.first.hint, hint); + }); }); group('$SentryBaggageHeader', () { @@ -510,7 +520,6 @@ void main() { expect(newBaggage.get('sentry-public_key'), 'public'); expect(newBaggage.get('sentry-release'), 'release'); expect(newBaggage.get('sentry-environment'), 'environment'); - expect(newBaggage.get('sentry-user_segment'), 'segment'); expect(newBaggage.get('sentry-transaction'), 'name'); expect(newBaggage.get('sentry-sample_rate'), '1'); expect(newBaggage.getSampleRand(), 0.8); @@ -585,8 +594,6 @@ void main() { expect(context.publicKey, 'public'); expect(context.release, 'release'); expect(context.environment, 'environment'); - // ignore: deprecated_member_use_from_same_package - expect(context.userSegment, 'segment'); expect(context.transaction, 'name'); expect(context.sampleRate, '1'); expect(context.sampled, 'true'); @@ -603,7 +610,6 @@ class Fixture { final user = SentryUser( id: 'id', - segment: 'segment', ); final hub = MockHub(); diff --git a/dart/test/sentry_traces_sampler_test.dart b/dart/test/sentry_traces_sampler_test.dart index 3fbcb85772..8d0ca97f02 100644 --- a/dart/test/sentry_traces_sampler_test.dart +++ b/dart/test/sentry_traces_sampler_test.dart @@ -80,6 +80,21 @@ void main() { expect(sut.sample(context).sampled, false); }); + test('does not sample if tracesSampleRate and tracesSampleRate are null', () { + final sut = fixture.getSut(tracesSampleRate: null, tracesSampler: null); + + final trContext = SentryTransactionContext( + 'name', + 'op', + ); + final context = SentrySamplingContext(trContext, {}); + final samplingDecision = sut.sample(context); + + expect(samplingDecision.sampleRate, isNull); + expect(samplingDecision.sampleRand, isNull); + expect(samplingDecision.sampled, false); + }); + test('tracesSampler exception is handled', () { fixture.options.automatedTestMode = false; final sut = fixture.getSut(debug: true); @@ -101,54 +116,6 @@ void main() { expect(fixture.loggedException, exception); expect(fixture.loggedLevel, SentryLevel.error); }); - - test('when no tracesSampleRate is set, do not sample with enableTracing null', - () { - final sampler = fixture.getSut(tracesSampleRate: null, enableTracing: null); - final trContext = SentryTransactionContext( - 'name', - 'op', - parentSamplingDecision: null, - ); - final context = SentrySamplingContext(trContext, {}); - final samplingDecision = sampler.sample(context); - - expect(samplingDecision.sampleRate, isNull); - expect(samplingDecision.sampled, false); - }); - - test( - 'when no tracesSampleRate is set, do not sample with enableTracing false', - () { - final sampler = - fixture.getSut(tracesSampleRate: null, enableTracing: false); - final trContext = SentryTransactionContext( - 'name', - 'op', - parentSamplingDecision: null, - ); - final context = SentrySamplingContext(trContext, {}); - final samplingDecision = sampler.sample(context); - - expect(samplingDecision.sampleRate, isNull); - expect(samplingDecision.sampled, false); - }); - - test( - 'when no tracesSampleRate is set, uses default rate with enableTracing true', - () { - final sampler = fixture.getSut(tracesSampleRate: null, enableTracing: true); - final trContext = SentryTransactionContext( - 'name', - 'op', - parentSamplingDecision: null, - ); - final context = SentrySamplingContext(trContext, {}); - final samplingDecision = sampler.sample(context); - - expect(samplingDecision.sampled, true); - expect(1.0, samplingDecision.sampleRate); - }); } class Fixture { @@ -161,14 +128,11 @@ class Fixture { double? tracesSampleRate = 1.0, TracesSamplerCallback? tracesSampler, bool debug = false, - bool? enableTracing, }) { options.tracesSampleRate = tracesSampleRate; options.tracesSampler = tracesSampler; options.debug = debug; options.logger = mockLogger; - // ignore: deprecated_member_use_from_same_package - options.enableTracing = enableTracing; return SentryTracesSampler(options); } diff --git a/dart/test/sentry_user_feedback_test.dart b/dart/test/sentry_user_feedback_test.dart deleted file mode 100644 index c724f6d8c1..0000000000 --- a/dart/test/sentry_user_feedback_test.dart +++ /dev/null @@ -1,243 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:sentry/sentry.dart'; -import 'package:sentry/src/sentry_item_type.dart'; -import 'package:test/test.dart'; - -import 'mocks.dart'; -import 'mocks/mock_transport.dart'; -import 'test_utils.dart'; - -void main() { - // ignore: deprecated_member_use_from_same_package - group('$SentryUserFeedback', () { - final id = SentryId.newId(); - - // ignore: deprecated_member_use_from_same_package - final feedback = SentryUserFeedback( - eventId: id, - comments: 'this is awesome', - email: 'sentry@example.com', - name: 'Rockstar Developer', - unknown: testUnknown, - ); - final feedbackJson = { - 'event_id': id.toString(), - 'comments': 'this is awesome', - 'email': 'sentry@example.com', - 'name': 'Rockstar Developer', - }; - feedbackJson.addAll(testUnknown); - - test('toJson', () { - final json = feedback.toJson(); - expect( - MapEquality().equals(feedbackJson, json), - true, - ); - }); - - test('fromJson', () { - final feedback = SentryRuntime.fromJson(feedbackJson); - final json = feedback.toJson(); - - expect( - MapEquality().equals(feedbackJson, json), - true, - ); - }); - - test('copyWith', () { - final id = SentryId.newId(); - // ignore: deprecated_member_use_from_same_package - final feedback = SentryUserFeedback( - eventId: id, - comments: 'this is awesome', - email: 'sentry@example.com', - name: 'Rockstar Developer', - ); - - final copyId = SentryId.newId(); - final copy = feedback.copyWith( - eventId: copyId, - comments: 'actually it is not', - email: 'example@example.com', - name: '10x developer', - ); - - expect(copy.eventId.toString(), copyId.toString()); - expect(copy.comments, 'actually it is not'); - expect(copy.email, 'example@example.com'); - expect(copy.name, '10x developer'); - }); - - test('disallow empty id', () { - final id = SentryId.empty(); - // ignore: deprecated_member_use_from_same_package - expect(() => SentryUserFeedback(eventId: id), - throwsA(isA())); - }); - }); - - // ignore: deprecated_member_use_from_same_package - group('$SentryUserFeedback to envelops', () { - test('to envelope', () { - // ignore: deprecated_member_use_from_same_package - final feedback = SentryUserFeedback( - eventId: SentryId.newId(), - name: 'test', - ); - // ignore: deprecated_member_use_from_same_package - final envelope = SentryEnvelope.fromUserFeedback( - feedback, - SdkVersion(name: 'a', version: 'b'), - dsn: fakeDsn, - ); - - expect(envelope.items.length, 1); - expect( - envelope.items.first.header.type, - SentryItemType.userFeedback, - ); - expect(envelope.header.eventId.toString(), feedback.eventId.toString()); - expect(envelope.header.dsn, fakeDsn); - }); - }); - - // ignore: deprecated_member_use_from_same_package - test('sending $SentryUserFeedback', () async { - final fixture = Fixture(); - final sut = fixture.getSut(); - // ignore: deprecated_member_use_from_same_package - await sut.captureUserFeedback(SentryUserFeedback( - eventId: SentryId.newId(), - name: 'test', - )); - - expect(fixture.transport.envelopes.length, 1); - }); - - // ignore: deprecated_member_use_from_same_package - test('cannot create $SentryUserFeedback with empty id', () async { - expect( - // ignore: deprecated_member_use_from_same_package - () => SentryUserFeedback(eventId: const SentryId.empty()), - throwsA(isA()), - ); - }); - - // ignore: deprecated_member_use_from_same_package - test('do not send $SentryUserFeedback when disabled', () async { - final fixture = Fixture(); - final sut = fixture.getSut(); - await sut.close(); - // ignore: deprecated_member_use_from_same_package - await sut.captureUserFeedback( - // ignore: deprecated_member_use_from_same_package - SentryUserFeedback( - eventId: SentryId.newId(), - name: 'test', - ), - ); - - expect(fixture.transport.envelopes.length, 0); - }); - - // ignore: deprecated_member_use_from_same_package - test('do not send $SentryUserFeedback with empty id', () async { - final fixture = Fixture(); - final sut = fixture.getSut(); - await sut.close(); - // ignore: deprecated_member_use_from_same_package - await sut.captureUserFeedback( - SentryUserFeedbackWithoutAssert( - eventId: SentryId.empty(), - ), - ); - - expect(fixture.transport.envelopes.length, 0); - }); - - test('captureUserFeedback does not throw', () async { - final options = defaultTestOptions()..automatedTestMode = false; - final transport = ThrowingTransport(); - options.transport = transport; - final sut = Hub(options); - - await expectLater(() async { - // ignore: deprecated_member_use_from_same_package - await sut.captureUserFeedback( - // ignore: deprecated_member_use_from_same_package - SentryUserFeedback(eventId: SentryId.newId(), name: 'name'), - ); - }, returnsNormally); - }); -} - -class Fixture { - late MockTransport transport; - - Hub getSut() { - final options = defaultTestOptions(); - transport = MockTransport(); - options.transport = transport; - return Hub(options); - } -} - -// You cannot create an instance of SentryUserFeedback with an empty id. -// In order to test that UserFeedback with an empty id is not sent -// we need to implement it and remove the assert. -// ignore: deprecated_member_use_from_same_package -class SentryUserFeedbackWithoutAssert implements SentryUserFeedback { - SentryUserFeedbackWithoutAssert({ - required this.eventId, - this.name, - this.email, - this.comments, - this.unknown, - }); - - @override - final SentryId eventId; - - @override - final String? name; - - @override - final String? email; - - @override - final String? comments; - - @override - Map? unknown; - - @override - Map toJson() { - return { - ...?unknown, - 'event_id': eventId.toString(), - if (name != null) 'name': name, - if (email != null) 'email': email, - if (comments != null) 'comments': comments, - }; - } - - @override - // ignore: deprecated_member_use_from_same_package - SentryUserFeedback copyWith({ - SentryId? eventId, - String? name, - String? email, - String? comments, - }) { - // ignore: deprecated_member_use_from_same_package - return SentryUserFeedback( - eventId: eventId ?? this.eventId, - name: name ?? this.name, - email: email ?? this.email, - comments: comments ?? this.comments, - unknown: unknown, - ); - } -} diff --git a/dart/test/stack_trace_test.dart b/dart/test/stack_trace_test.dart index 9e38eef032..4507e8f916 100644 --- a/dart/test/stack_trace_test.dart +++ b/dart/test/stack_trace_test.dart @@ -3,11 +3,11 @@ // found in the LICENSE file. import 'package:sentry/src/origin.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; -import 'mocks/mock_platform_checker.dart'; import 'test_utils.dart'; void main() { @@ -284,13 +284,13 @@ isolate_instructions: 10fa27070, vm_instructions: 10fa21e20 final fixture = Fixture(); // Test for web platform - fixture.options.platformChecker = MockPlatformChecker(isWebValue: true); + fixture.options.platform = MockPlatform(isWeb: true); final webSut = fixture.getSut(); var webFrame = webSut.encodeStackTraceFrame(frame)!; expect(webFrame.platform, 'javascript'); // Test for non-web platform - fixture.options.platformChecker = MockPlatformChecker(isWebValue: false); + fixture.options.platform = MockPlatform(isWeb: false); final nativeFrameBeforeSut = fixture.getSut(); var nativeFrameBefore = nativeFrameBeforeSut.encodeStackTraceFrame(frame)!; @@ -307,7 +307,7 @@ isolate_instructions: 10fa27070, vm_instructions: 10fa21e20 } class Fixture { - final options = defaultTestOptions(MockPlatformChecker(isWebValue: false)); + final options = defaultTestOptions()..platform = MockPlatform(isWeb: false); SentryStackTraceFactory getSut({ List inAppIncludes = const [], diff --git a/dart/test/test_utils.dart b/dart/test/test_utils.dart index 344f135d2b..cb9fc9a479 100644 --- a/dart/test/test_utils.dart +++ b/dart/test/test_utils.dart @@ -8,6 +8,7 @@ import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:http/testing.dart'; import 'package:sentry/sentry.dart'; +import 'package:sentry/src/platform/platform.dart'; import 'package:sentry/src/version.dart'; import 'package:test/test.dart'; @@ -18,8 +19,9 @@ const String _testDsnWithPath = const String _testDsnWithPort = 'https://public:secret@sentry.example.com:8888/1'; -SentryOptions defaultTestOptions([PlatformChecker? checker]) { - return SentryOptions(dsn: testDsn, checker: checker) +SentryOptions defaultTestOptions( + {Platform? platform, RuntimeChecker? checker}) { + return SentryOptions(dsn: testDsn, platform: platform, checker: checker) ..automatedTestMode = true; } diff --git a/dart/test/utils/tracing_utils_test.dart b/dart/test/utils/tracing_utils_test.dart index 134997afae..8c73a1a54a 100644 --- a/dart/test/utils/tracing_utils_test.dart +++ b/dart/test/utils/tracing_utils_test.dart @@ -115,7 +115,7 @@ void main() { test('overwrites duplicate key values', () { final headers = {}; final oldValue = - 'other-vendor-value=foo,sentry-trace_id=${SentryId.newId()},sentry-public_key=oldPublicKey,sentry-release=oldRelease,sentry-environment=oldEnvironment,sentry-user_id=oldUserId,sentry-user_segment=oldUserSegment,sentry-transaction=oldTransaction,sentry-sample_rate=0.5'; + 'other-vendor-value=foo,sentry-trace_id=${SentryId.newId()},sentry-public_key=oldPublicKey,sentry-release=oldRelease,sentry-environment=oldEnvironment,sentry-user_id=oldUserId,sentry-transaction=oldTransaction,sentry-sample_rate=0.5'; headers['baggage'] = oldValue; @@ -125,7 +125,7 @@ void main() { addBaggageHeaderFromSpan(sut, headers); expect(headers[baggage!.name], - 'other-vendor-value=foo,sentry-trace_id=${sut.context.traceId},sentry-public_key=public,sentry-release=release,sentry-environment=environment,sentry-user_segment=segment,sentry-transaction=name,sentry-sample_rate=1,sentry-sampled=true'); + 'other-vendor-value=foo,sentry-trace_id=${sut.context.traceId},sentry-public_key=public,sentry-release=release,sentry-environment=environment,sentry-transaction=name,sentry-sample_rate=1,sentry-sampled=true'); }); }); @@ -177,7 +177,6 @@ class Fixture { final _user = SentryUser( id: 'id', - segment: 'segment', ); SentryTracer getSut() { diff --git a/dart/test/version_test.dart b/dart/test/version_test.dart index f2022bbba2..ada7310338 100644 --- a/dart/test/version_test.dart +++ b/dart/test/version_test.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. @TestOn('vm') -library dart_test; +library; import 'dart:io'; diff --git a/dio/example/example.dart b/dio/example/example.dart index f590a4602e..289b26e133 100644 --- a/dio/example/example.dart +++ b/dio/example/example.dart @@ -16,7 +16,6 @@ Future main() async { options.sendDefaultPii = true; options.maxRequestBodySize = MaxRequestBodySize.small; - options.maxResponseBodySize = MaxResponseBodySize.small; }, appRunner: runApp, // Init your App. ); diff --git a/dio/lib/sentry_dio.dart b/dio/lib/sentry_dio.dart index 5c1ce5d084..d0238e4c10 100644 --- a/dio/lib/sentry_dio.dart +++ b/dio/lib/sentry_dio.dart @@ -1,4 +1,4 @@ -library sentry_dio; +library; export 'src/sentry_dio_extension.dart'; diff --git a/dio/lib/src/dio_event_processor.dart b/dio/lib/src/dio_event_processor.dart index afeb692be4..0adbbf18fb 100644 --- a/dio/lib/src/dio_event_processor.dart +++ b/dio/lib/src/dio_event_processor.dart @@ -1,7 +1,5 @@ // ignore_for_file: deprecated_member_use -import 'dart:convert'; - import 'package:dio/dio.dart'; import 'package:sentry/sentry.dart'; @@ -34,17 +32,13 @@ class DioEventProcessor implements EventProcessor { return event; } - final response = _responseFrom(dioError); + hint.response ??= _responseFrom(dioError); - var contexts = event.contexts; - if (event.contexts.response == null) { - contexts = contexts.copyWith(response: response); - } // Don't override just parts of the original request. // Keep the original one or if there's none create one. event = event.copyWith( request: event.request ?? _requestFrom(dioError), - contexts: contexts, + contexts: event.contexts, ); return event; @@ -86,77 +80,31 @@ class DioEventProcessor implements EventProcessor { final headers = response?.headers.map.map( (key, value) => MapEntry(key, value.join('; ')), ); + final contentLengthHeader = headers?['content-length']; + int? contentLength; + if (contentLengthHeader != null) { + contentLength = int.tryParse(contentLengthHeader); + } return SentryResponse( headers: _options.sendDefaultPii ? headers : null, - bodySize: _getBodySize( - dioError.response?.data, - dioError.requestOptions.responseType, - ), + bodySize: contentLength, statusCode: response?.statusCode, - data: _getResponseData( - dioError.response?.data, - dioError.requestOptions.responseType, - ), + data: _getResponseData(dioError.response?.data, contentLength), ); } - /// Returns the response data, if possible according to the users settings. - Object? _getResponseData(Object? data, ResponseType responseType) { + Object? _getResponseData(Object? data, int? contentLength) { if (!_options.sendDefaultPii || data == null) { return null; } - switch (responseType) { - case ResponseType.json: - // ignore: invalid_use_of_internal_member - final jsData = utf8JsonEncoder.convert(data); - if (_options.maxResponseBodySize.shouldAddBody(jsData.length)) { - return data; - } - break; - case ResponseType.stream: - break; // No support for logging stream body. - case ResponseType.plain: - if (data is String && - _options.maxResponseBodySize.shouldAddBody(data.codeUnits.length)) { - return data; - } - break; - case ResponseType.bytes: - if (data is List && - _options.maxResponseBodySize.shouldAddBody(data.length)) { - return data; - } - break; - } - return null; - } - - int? _getBodySize(Object? data, ResponseType responseType) { - if (data == null) { + if (contentLength == null) { return null; } - switch (responseType) { - case ResponseType.json: - return json.encode(data).codeUnits.length; - case ResponseType.stream: - if (data is String) { - return data.length; - } else { - return null; - } - case ResponseType.plain: - if (data is String) { - return data.codeUnits.length; - } else { - return null; - } - case ResponseType.bytes: - if (data is List) { - return data.length; - } else { - return null; - } + // ignore: invalid_use_of_internal_member + if (contentLength > Hint.maxResponseBodySize) { + return null; } + return data; } } diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 26c94b6264..cb254e411b 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.14.0'; +const String sdkVersion = '9.0.0-alpha.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index d4b5276696..4f6f000fea 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,13 +1,13 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 8.14.0 +version: 9.0.0-alpha.1 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues documentation: https://docs.sentry.io/platforms/dart/integrations/dio/ environment: - sdk: '>=2.17.0 <4.0.0' + sdk: '>=3.5.0 <4.0.0' platforms: android: @@ -19,7 +19,7 @@ platforms: dependencies: dio: ^5.0.0 - sentry: 8.14.0 + sentry: 9.0.0-alpha.1 dev_dependencies: meta: ^1.3.0 diff --git a/dio/test/dio_event_processor_test.dart b/dio/test/dio_event_processor_test.dart index 9786828841..d5878b04cc 100644 --- a/dio/test/dio_event_processor_test.dart +++ b/dio/test/dio_event_processor_test.dart @@ -133,26 +133,25 @@ void main() { expect(processedEvent.request?.headers, {}); }); - test('request body is included according to $MaxResponseBodySize', - () async { + test('request body is included according to $MaxRequestBodySize', () async { final scenarios = [ // never - MaxBodySizeTestConfig(MaxRequestBodySize.never, 0, false), - MaxBodySizeTestConfig(MaxRequestBodySize.never, 4001, false), - MaxBodySizeTestConfig(MaxRequestBodySize.never, 10001, false), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.never, 0, false), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.never, 4001, false), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.never, 10001, false), // always - MaxBodySizeTestConfig(MaxRequestBodySize.always, 0, true), - MaxBodySizeTestConfig(MaxRequestBodySize.always, 4001, true), - MaxBodySizeTestConfig(MaxRequestBodySize.always, 10001, true), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.always, 0, true), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.always, 4001, true), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.always, 10001, true), // small - MaxBodySizeTestConfig(MaxRequestBodySize.small, 0, true), - MaxBodySizeTestConfig(MaxRequestBodySize.small, 4000, true), - MaxBodySizeTestConfig(MaxRequestBodySize.small, 4001, false), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.small, 0, true), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.small, 4000, true), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.small, 4001, false), // medium - MaxBodySizeTestConfig(MaxRequestBodySize.medium, 0, true), - MaxBodySizeTestConfig(MaxRequestBodySize.medium, 4001, true), - MaxBodySizeTestConfig(MaxRequestBodySize.medium, 10000, true), - MaxBodySizeTestConfig(MaxRequestBodySize.medium, 10001, false), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.medium, 0, true), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.medium, 4001, true), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.medium, 10000, true), + MaxRequestBodySizeTestConfig(MaxRequestBodySize.medium, 10001, false), ]; for (final scenario in scenarios) { @@ -208,6 +207,7 @@ void main() { headers: Headers.fromMap(>{ 'foo': ['bar'], 'set-cookie': ['foo=bar'], + 'content-length': ['6'], }), requestOptions: request, isRedirect: true, @@ -222,17 +222,20 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event, Hint()) as SentryEvent; + final hint = Hint(); + final processedEvent = sut.apply(event, hint) as SentryEvent; + final capturedResponse = hint.response; expect(processedEvent.throwable, event.throwable); - expect(processedEvent.contexts.response, isNotNull); - expect(processedEvent.contexts.response?.bodySize, 6); - expect(processedEvent.contexts.response?.statusCode, 200); - expect(processedEvent.contexts.response?.headers, { + expect(capturedResponse, isNotNull); + expect(capturedResponse?.bodySize, 6); + expect(capturedResponse?.statusCode, 200); + expect(capturedResponse?.headers, { 'foo': 'bar', 'set-cookie': 'foo=bar', + 'content-length': '6', }); - expect(processedEvent.contexts.response?.cookies, 'foo=bar'); + expect(capturedResponse?.cookies, 'foo=bar'); }); test('$DioEventProcessor adds response without PII', () { @@ -249,6 +252,7 @@ void main() { data: 'foobar', headers: Headers.fromMap(>{ 'foo': ['bar'], + 'content-length': ['6'], }), requestOptions: request, isRedirect: true, @@ -265,40 +269,35 @@ void main() { ); final processedEvent = sut.apply(event, Hint()) as SentryEvent; + final hint = Hint(); + sut.apply(event, hint) as SentryEvent; + final capturedResponse = hint.response; + expect(processedEvent.throwable, event.throwable); - expect(processedEvent.contexts.response, isNotNull); - expect(processedEvent.contexts.response?.bodySize, 6); - expect(processedEvent.contexts.response?.statusCode, 200); - expect(processedEvent.contexts.response?.headers, {}); + expect(capturedResponse, isNotNull); + expect(capturedResponse?.bodySize, 6); + expect(capturedResponse?.statusCode, 200); + expect(capturedResponse?.headers, {}); }); - test('response body is included according to $MaxResponseBodySize', - () async { + test('response body is included if smaller 0.15mb', () async { final scenarios = [ - // never - MaxBodySizeTestConfig(MaxResponseBodySize.never, 0, false), - MaxBodySizeTestConfig(MaxResponseBodySize.never, 4001, false), - MaxBodySizeTestConfig(MaxResponseBodySize.never, 10001, false), - // always - MaxBodySizeTestConfig(MaxResponseBodySize.always, 0, true), - MaxBodySizeTestConfig(MaxResponseBodySize.always, 4001, true), - MaxBodySizeTestConfig(MaxResponseBodySize.always, 10001, true), - // small - MaxBodySizeTestConfig(MaxResponseBodySize.small, 0, true), - MaxBodySizeTestConfig(MaxResponseBodySize.small, 4000, true), - MaxBodySizeTestConfig(MaxResponseBodySize.small, 4001, false), - // medium - MaxBodySizeTestConfig(MaxResponseBodySize.medium, 0, true), - MaxBodySizeTestConfig(MaxResponseBodySize.medium, 4001, true), - MaxBodySizeTestConfig(MaxResponseBodySize.medium, 10000, true), - MaxBodySizeTestConfig(MaxResponseBodySize.medium, 10001, false), + // Headers with content-length + MaxResponseBodySizeTestConfig(0, true, true), + MaxResponseBodySizeTestConfig(4001, true, true), + MaxResponseBodySizeTestConfig(10001, true, true), + MaxResponseBodySizeTestConfig(157287, true, false), + // // Headers without content-length + MaxResponseBodySizeTestConfig(0, false, false), + MaxResponseBodySizeTestConfig(4001, false, false), + MaxResponseBodySizeTestConfig(10001, false, false), + MaxResponseBodySizeTestConfig(157287, false, false), ]; for (final scenario in scenarios) { final sut = fixture.getSut( sendDefaultPii: true, captureFailedRequests: true, - maxResponseBodySize: scenario.maxBodySize, ); final data = List.generate(scenario.contentLength, (index) => 0); @@ -308,12 +307,19 @@ void main() { responseType: ResponseType.bytes, ); final throwable = Exception(); + final headers = { + 'content-length': ['${scenario.contentLength}'], + }; + final dioError = DioError( requestOptions: request, response: Response( requestOptions: request, statusCode: 401, data: data, + headers: scenario.headersHaveContentLength + ? Headers.fromMap(headers) + : null, ), ); final event = SentryEvent( @@ -323,10 +329,15 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event, Hint()) as SentryEvent; - final capturedResponse = processedEvent.contexts.response; + final hint = Hint(); + sut.apply(event, hint) as SentryEvent; + final capturedResponse = hint.response; expect(capturedResponse, isNotNull); + expect( + capturedResponse?.bodySize, + scenario.headersHaveContentLength ? scenario.contentLength : isNull, + ); expect( capturedResponse?.data, scenario.shouldBeIncluded ? isNotNull : isNull, @@ -360,12 +371,18 @@ void main() { responseType: responseType, ); final throwable = Exception(); + final headers = { + 'content-length': [ + '9001', + ], // Dummy content size, not relevant for this test + }; final dioError = DioError( requestOptions: request, response: Response( requestOptions: request, statusCode: 401, data: data, + headers: Headers.fromMap(headers), ), ); @@ -378,8 +395,9 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event, Hint()) as SentryEvent; - final capturedResponse = processedEvent.contexts.response; + final hint = Hint(); + sut.apply(event, hint) as SentryEvent; + final capturedResponse = hint.response; expect(capturedResponse, isNotNull); expect(capturedResponse?.data, data); @@ -445,14 +463,12 @@ class Fixture { bool sendDefaultPii = false, bool captureFailedRequests = true, MaxRequestBodySize maxRequestBodySize = MaxRequestBodySize.always, - MaxResponseBodySize maxResponseBodySize = MaxResponseBodySize.always, }) { return DioEventProcessor( options ..sendDefaultPii = sendDefaultPii ..captureFailedRequests = captureFailedRequests - ..maxRequestBodySize = maxRequestBodySize - ..maxResponseBodySize = maxResponseBodySize, + ..maxRequestBodySize = maxRequestBodySize, ); } @@ -465,8 +481,8 @@ class Fixture { } } -class MaxBodySizeTestConfig { - MaxBodySizeTestConfig( +class MaxRequestBodySizeTestConfig { + MaxRequestBodySizeTestConfig( this.maxBodySize, this.contentLength, this.shouldBeIncluded, @@ -478,3 +494,17 @@ class MaxBodySizeTestConfig { Matcher get matcher => shouldBeIncluded ? isNotNull : isNull; } + +class MaxResponseBodySizeTestConfig { + MaxResponseBodySizeTestConfig( + this.contentLength, + this.headersHaveContentLength, + this.shouldBeIncluded, + ); + + final int contentLength; + final bool headersHaveContentLength; + final bool shouldBeIncluded; + + Matcher get matcher => shouldBeIncluded ? isNotNull : isNull; +} diff --git a/dio/test/mocks/mock_hub.dart b/dio/test/mocks/mock_hub.dart index d798b551ac..1a011a3cf5 100644 --- a/dio/test/mocks/mock_hub.dart +++ b/dio/test/mocks/mock_hub.dart @@ -11,8 +11,6 @@ class MockHub with NoSuchMethodProvider implements Hub { List addBreadcrumbCalls = []; List bindClientCalls = []; - // ignore: deprecated_member_use - List userFeedbackCalls = []; List captureTransactionCalls = []; int closeCalls = 0; bool _isEnabled = true; @@ -117,17 +115,12 @@ class MockHub with NoSuchMethodProvider implements Hub { Future captureTransaction( SentryTransaction transaction, { SentryTraceContextHeader? traceContext, + Hint? hint, }) async { captureTransactionCalls.add(transaction); return transaction.eventId; } - @override - // ignore: deprecated_member_use - Future captureUserFeedback(SentryUserFeedback userFeedback) async { - userFeedbackCalls.add(userFeedback); - } - @override ISentrySpan? getSpan() { getSpanCalls++; diff --git a/dio/test/tracing_client_adapter_test.dart b/dio/test/tracing_client_adapter_test.dart index 680825b34f..d4f6299366 100644 --- a/dio/test/tracing_client_adapter_test.dart +++ b/dio/test/tracing_client_adapter_test.dart @@ -137,7 +137,9 @@ void main() { test('set headers from propagationContext when tracing is disabled', () async { - fixture._options.enableTracing = false; + fixture._options.tracesSampleRate = null; + fixture._options.tracesSampler = null; + final sut = fixture.getSut( client: fixture.getClient(statusCode: 200, reason: 'OK'), ); diff --git a/dio/test/version_test.dart b/dio/test/version_test.dart index 2e0c6a8b14..ebfddbcf10 100644 --- a/dio/test/version_test.dart +++ b/dio/test/version_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dio_test; +library; import 'dart:io'; diff --git a/drift/analysis_options.yaml b/drift/analysis_options.yaml index c5f7c0d066..7119dc352d 100644 --- a/drift/analysis_options.yaml +++ b/drift/analysis_options.yaml @@ -24,7 +24,6 @@ analyzer: linter: rules: - prefer_final_locals - - public_member_api_docs - prefer_single_quotes - prefer_relative_imports - unnecessary_brace_in_string_interps diff --git a/drift/example/database.g.dart b/drift/example/database.g.dart index 1f9d234456..3f01770182 100644 --- a/drift/example/database.g.dart +++ b/drift/example/database.g.dart @@ -160,6 +160,15 @@ class TodoItem extends DataClass implements Insertable { content: content ?? this.content, category: category.present ? category.value : this.category, ); + TodoItem copyWithCompanion(TodoItemsCompanion data) { + return TodoItem( + id: data.id.present ? data.id.value : this.id, + title: data.title.present ? data.title.value : this.title, + content: data.content.present ? data.content.value : this.content, + category: data.category.present ? data.category.value : this.category, + ); + } + @override String toString() { return (StringBuffer('TodoItem(') @@ -260,6 +269,7 @@ class TodoItemsCompanion extends UpdateCompanion { abstract class _$AppDatabase extends GeneratedDatabase { _$AppDatabase(QueryExecutor e) : super(e); + $AppDatabaseManager get managers => $AppDatabaseManager(this); late final $TodoItemsTable todoItems = $TodoItemsTable(this); @override Iterable> get allTables => @@ -267,3 +277,155 @@ abstract class _$AppDatabase extends GeneratedDatabase { @override List get allSchemaEntities => [todoItems]; } + +typedef $$TodoItemsTableCreateCompanionBuilder = TodoItemsCompanion Function({ + Value id, + required String title, + required String content, + Value category, +}); +typedef $$TodoItemsTableUpdateCompanionBuilder = TodoItemsCompanion Function({ + Value id, + Value title, + Value content, + Value category, +}); + +class $$TodoItemsTableFilterComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get title => $composableBuilder( + column: $table.title, builder: (column) => ColumnFilters(column)); + + ColumnFilters get content => $composableBuilder( + column: $table.content, builder: (column) => ColumnFilters(column)); + + ColumnFilters get category => $composableBuilder( + column: $table.category, builder: (column) => ColumnFilters(column)); +} + +class $$TodoItemsTableOrderingComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get title => $composableBuilder( + column: $table.title, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get content => $composableBuilder( + column: $table.content, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get category => $composableBuilder( + column: $table.category, builder: (column) => ColumnOrderings(column)); +} + +class $$TodoItemsTableAnnotationComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get title => + $composableBuilder(column: $table.title, builder: (column) => column); + + GeneratedColumn get content => + $composableBuilder(column: $table.content, builder: (column) => column); + + GeneratedColumn get category => + $composableBuilder(column: $table.category, builder: (column) => column); +} + +class $$TodoItemsTableTableManager extends RootTableManager< + _$AppDatabase, + $TodoItemsTable, + TodoItem, + $$TodoItemsTableFilterComposer, + $$TodoItemsTableOrderingComposer, + $$TodoItemsTableAnnotationComposer, + $$TodoItemsTableCreateCompanionBuilder, + $$TodoItemsTableUpdateCompanionBuilder, + (TodoItem, BaseReferences<_$AppDatabase, $TodoItemsTable, TodoItem>), + TodoItem, + PrefetchHooks Function()> { + $$TodoItemsTableTableManager(_$AppDatabase db, $TodoItemsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$TodoItemsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$TodoItemsTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$TodoItemsTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value title = const Value.absent(), + Value content = const Value.absent(), + Value category = const Value.absent(), + }) => + TodoItemsCompanion( + id: id, + title: title, + content: content, + category: category, + ), + createCompanionCallback: ({ + Value id = const Value.absent(), + required String title, + required String content, + Value category = const Value.absent(), + }) => + TodoItemsCompanion.insert( + id: id, + title: title, + content: content, + category: category, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$TodoItemsTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $TodoItemsTable, + TodoItem, + $$TodoItemsTableFilterComposer, + $$TodoItemsTableOrderingComposer, + $$TodoItemsTableAnnotationComposer, + $$TodoItemsTableCreateCompanionBuilder, + $$TodoItemsTableUpdateCompanionBuilder, + (TodoItem, BaseReferences<_$AppDatabase, $TodoItemsTable, TodoItem>), + TodoItem, + PrefetchHooks Function()>; + +class $AppDatabaseManager { + final _$AppDatabase _db; + $AppDatabaseManager(this._db); + $$TodoItemsTableTableManager get todoItems => + $$TodoItemsTableTableManager(_db, _db.todoItems); +} diff --git a/drift/example/example.dart b/drift/example/example.dart index bfe8b6d8e6..02a4b09998 100644 --- a/drift/example/example.dart +++ b/drift/example/example.dart @@ -22,18 +22,45 @@ Future main() async { Future runApp() async { final tr = Sentry.startTransaction('drift', 'op', bindToScope: true); - final executor = SentryQueryExecutor( - () => NativeDatabase.memory(), - databaseName: 'your_db_name', + final executor = NativeDatabase.memory().interceptWith( + SentryQueryInterceptor(databaseName: 'your_db_name'), ); + final db = AppDatabase(executor); - await db.into(db.todoItems).insert( + await db.transaction(() async { + await db.into(db.todoItems).insert( + TodoItemsCompanion.insert( + title: 'This is a test thing', + content: 'test', + ), + ); + + await db.transaction(() async { + await db.into(db.todoItems).insert( + TodoItemsCompanion.insert( + title: 'This is a test thing in the tx', + content: 'test', + ), + ); + }); + + await db.batch((batch) { + batch.insertAll(db.todoItems, [ + TodoItemsCompanion.insert(title: 'First entry', content: 'My content'), TodoItemsCompanion.insert( - title: 'This is a test thing', - content: 'test', + title: 'Another entry', + content: 'More content', ), - ); + ]); + }); + }); + + await db.batch((batch) async { + batch.insertAll(db.todoItems, [ + TodoItemsCompanion.insert(title: 'This is a test', content: 'test'), + ]); + }); final items = await db.select(db.todoItems).get(); print(items); diff --git a/drift/lib/sentry_drift.dart b/drift/lib/sentry_drift.dart index ba84220b42..8f160e44d3 100644 --- a/drift/lib/sentry_drift.dart +++ b/drift/lib/sentry_drift.dart @@ -1,3 +1,3 @@ -library sentry_drift; +library; -export 'src/sentry_query_executor.dart'; +export 'src/sentry_query_interceptor.dart'; diff --git a/drift/lib/src/constants.dart b/drift/lib/src/constants.dart new file mode 100644 index 0000000000..c096dbc0af --- /dev/null +++ b/drift/lib/src/constants.dart @@ -0,0 +1,2 @@ +const String integrationName = 'sentryDriftTracing'; +const String loggerName = 'sentry_drift'; diff --git a/drift/lib/src/sentry_query_executor.dart b/drift/lib/src/sentry_query_executor.dart deleted file mode 100644 index 63aaf77d3b..0000000000 --- a/drift/lib/src/sentry_query_executor.dart +++ /dev/null @@ -1,198 +0,0 @@ -import 'dart:async'; - -import 'package:drift/drift.dart'; -import 'package:meta/meta.dart'; -import 'package:sentry/sentry.dart'; - -import 'sentry_span_helper.dart'; -import 'sentry_transaction_executor.dart'; -import 'version.dart'; - -/// Signature of a function that opens a database connection when instructed to. -typedef DatabaseOpener = FutureOr Function(); - -/// The Sentry Query Executor. -/// -/// If the constructor parameter queryExecutor is null, [LazyDatabase] will be -/// used as a default. -@experimental -@Deprecated( - 'This will be replaced by SentryQueryInterceptor in the next major v9 ' - 'where you can use executor.interceptWith(...) to attach the SentryQueryInterceptor') -class SentryQueryExecutor extends QueryExecutor { - Hub _hub; - - final _spanHelper = SentrySpanHelper( - // ignore: invalid_use_of_internal_member - SentryTraceOrigins.autoDbDriftQueryExecutor, - ); - - final QueryExecutor _executor; - - final String _dbName; - - @internal - // ignore: public_member_api_docs - static const dbNameKey = 'db.name'; - - @internal - // ignore: public_member_api_docs - static const dbOp = 'db'; - - @internal - // ignore: public_member_api_docs - static const dbSystemKey = 'db.system'; - - @internal - // ignore: public_member_api_docs - static const dbSystem = 'sqlite'; - - bool _isOpen = false; - - /// Declares a [SentryQueryExecutor] that will run [opener] when the database is - /// first requested to be opened. You must specify the same [dialect] as the - /// underlying database has - SentryQueryExecutor( - DatabaseOpener opener, { - @internal Hub? hub, - @internal QueryExecutor? queryExecutor, - required String databaseName, - }) : _hub = hub ?? HubAdapter(), - _dbName = databaseName, - _executor = queryExecutor ?? LazyDatabase(opener) { - // ignore: invalid_use_of_internal_member - final options = _hub.options; - options.sdk.addIntegration('SentryDriftTracing'); - options.sdk.addPackage(packageName, sdkVersion); - _spanHelper.setHub(_hub); - } - - /// @nodoc - @internal - void setHub(Hub hub) { - _hub = hub; - _spanHelper.setHub(hub); - } - - @override - TransactionExecutor beginTransaction() { - final transactionExecutor = _executor.beginTransaction(); - final sentryTransactionExecutor = SentryTransactionExecutor( - transactionExecutor, - _hub, - dbName: _dbName, - ); - sentryTransactionExecutor.beginTransaction(); - return sentryTransactionExecutor; - } - - @override - Future runBatched(BatchedStatements statements) { - return _spanHelper.asyncWrapInSpan( - statements.toString(), - () async { - return await _executor.runBatched(statements); - }, - dbName: _dbName, - ); - } - - @override - Future ensureOpen(QueryExecutorUser user) { - if (_isOpen) { - return Future.value(true); - } - return _spanHelper.asyncWrapInSpan( - 'Open DB: $_dbName', - () async { - final res = await _executor.ensureOpen(user); - _isOpen = true; - return res; - }, - dbName: _dbName, - ); - } - - @override - Future runCustom(String statement, [List? args]) { - return _spanHelper.asyncWrapInSpan( - statement, - () async { - return await _executor.runCustom(statement, args); - }, - dbName: _dbName, - ); - } - - @override - Future runDelete(String statement, List args) { - return _spanHelper.asyncWrapInSpan( - statement, - () async { - return await _executor.runDelete(statement, args); - }, - dbName: _dbName, - ); - } - - @override - Future runInsert(String statement, List args) { - return _spanHelper.asyncWrapInSpan( - statement, - () async { - return await _executor.runInsert(statement, args); - }, - dbName: _dbName, - ); - } - - @override - Future>> runSelect( - String statement, - List args, - ) { - return _spanHelper.asyncWrapInSpan( - statement, - () async { - return await _executor.runSelect(statement, args); - }, - dbName: _dbName, - ); - } - - @override - Future runUpdate(String statement, List args) { - return _spanHelper.asyncWrapInSpan( - statement, - () async { - return await _executor.runUpdate(statement, args); - }, - dbName: _dbName, - ); - } - - @override - // ignore: override_on_non_overriding_member, public_member_api_docs - QueryExecutor beginExclusive() { - final dynamic uncheckedExecutor = _executor; - try { - return uncheckedExecutor.beginExclusive() as QueryExecutor; - } on NoSuchMethodError catch (_) { - throw Exception('This method is not supported in Drift versions <2.19.0'); - } - } - - @override - Future close() { - return _spanHelper.asyncWrapInSpan( - 'Close DB: $_dbName', - () async { - return await _executor.close(); - }, - dbName: _dbName, - ); - } - - @override - SqlDialect get dialect => _executor.dialect; -} diff --git a/drift/lib/src/sentry_query_interceptor.dart b/drift/lib/src/sentry_query_interceptor.dart new file mode 100644 index 0000000000..89bcabdf65 --- /dev/null +++ b/drift/lib/src/sentry_query_interceptor.dart @@ -0,0 +1,171 @@ +// ignore_for_file: invalid_use_of_internal_member + +import 'dart:async'; + +import 'package:drift/drift.dart'; +import 'package:meta/meta.dart'; +import 'package:sentry/sentry.dart'; + +import 'constants.dart' as drift_constants; +import 'sentry_span_helper.dart'; +import 'version.dart'; + +/// A Sentry query interceptor that wraps database operations in performance monitoring spans. +/// +/// This interceptor tracks all database operations executed through a Drift database connection, +/// including transactions, batches, and individual CRUD operations. Each operation is captured +/// as a Sentry span with relevant context. +class SentryQueryInterceptor extends QueryInterceptor { + final String _dbName; + late final SentrySpanHelper _spanHelper; + bool _isDbOpen = false; + + @visibleForTesting + SentrySpanHelper get spanHelper => _spanHelper; + + SentryQueryInterceptor({required String databaseName, @internal Hub? hub}) + : _dbName = databaseName { + hub = hub ?? HubAdapter(); + _spanHelper = SentrySpanHelper( + SentryTraceOrigins.autoDbDriftQueryInterceptor, + hub: hub, + ); + final options = hub.options; + options.sdk.addIntegration(drift_constants.integrationName); + options.sdk.addPackage(packageName, sdkVersion); + } + + /// Wraps database operations in Sentry spans. + /// + /// This handles most CRUD operations but excludes transaction lifecycle methods + /// (begin/commit/rollback), which require maintaining an ongoing transaction span + /// across multiple operations. Those are handled separately via [SentrySpanHelper]. + Future _instrumentOperation( + String description, + FutureOr Function() execute, { + String? operation, + }) async => + _spanHelper.asyncWrapInSpan( + description, + () async => execute(), + dbName: _dbName, + operation: operation, + ); + + @override + Future ensureOpen(QueryExecutor executor, QueryExecutorUser user) { + if (_isDbOpen) { + return super.ensureOpen(executor, user); + } + return _instrumentOperation( + SentrySpanDescriptions.dbOpen(dbName: _dbName), + () async { + final result = await super.ensureOpen(executor, user); + _isDbOpen = true; + return result; + }, + operation: SentrySpanOperations.dbOpen, + ); + } + + @override + TransactionExecutor beginTransaction(QueryExecutor parent) { + return _spanHelper.beginTransaction( + () => super.beginTransaction(parent), + dbName: _dbName, + ); + } + + @override + Future close(QueryExecutor inner) { + return _instrumentOperation( + SentrySpanDescriptions.dbClose(dbName: _dbName), + () => super.close(inner), + operation: SentrySpanOperations.dbClose, + ); + } + + @override + Future runBatched( + QueryExecutor executor, + BatchedStatements statements, + ) { + final description = + SentrySpanDescriptions.dbBatch(statements: statements.statements); + return _instrumentOperation( + description, + () => super.runBatched(executor, statements), + operation: SentrySpanOperations.dbSqlBatch, + ); + } + + @override + Future commitTransaction(TransactionExecutor inner) { + return _spanHelper.finishTransaction(() => super.commitTransaction(inner)); + } + + @override + Future rollbackTransaction(TransactionExecutor inner) { + return _spanHelper.abortTransaction(() => super.rollbackTransaction(inner)); + } + + @override + Future runInsert( + QueryExecutor executor, + String statement, + List args, + ) { + return _instrumentOperation( + statement, + () => executor.runInsert(statement, args), + ); + } + + @override + Future runUpdate( + QueryExecutor executor, + String statement, + List args, + ) { + return _instrumentOperation( + statement, + () => executor.runUpdate(statement, args), + ); + } + + @override + Future runDelete( + QueryExecutor executor, + String statement, + List args, + ) { + return _instrumentOperation( + statement, + () => executor.runDelete(statement, args), + ); + } + + @override + Future runCustom( + QueryExecutor executor, + String statement, + List args, + ) { + return _instrumentOperation( + statement, + () => executor.runCustom(statement, args), + ); + } + + @override + Future>> runSelect( + QueryExecutor executor, + String statement, + List args, + ) { + return _instrumentOperation( + statement, + () => executor.runSelect(statement, args), + ); + } +} diff --git a/drift/lib/src/sentry_span_helper.dart b/drift/lib/src/sentry_span_helper.dart index 008a01a1a6..f9a04e0ed7 100644 --- a/drift/lib/src/sentry_span_helper.dart +++ b/drift/lib/src/sentry_span_helper.dart @@ -1,156 +1,172 @@ -// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: invalid_use_of_internal_member + +import 'dart:collection'; import 'package:meta/meta.dart'; import 'package:sentry/sentry.dart'; -import 'sentry_query_executor.dart'; +import 'constants.dart'; -/// @nodoc @internal class SentrySpanHelper { - /// @nodoc - Hub _hub = HubAdapter(); - - /// @nodoc + final Hub _hub; final String _origin; - /// @nodoc - SentrySpanHelper(this._origin); + /// Represents a stack of Drift transaction spans. + /// These are used to allow nested spans if the user nests Drift transactions. + /// If the transaction stack is empty, the spans are attached to the + /// active span in the Hub's scope. + final ListQueue _transactionStack = ListQueue(); - /// @nodoc - void setHub(Hub hub) { - _hub = hub; - } + @visibleForTesting + ListQueue get transactionStack => _transactionStack; + + SentrySpanHelper(this._origin, {Hub? hub}) : _hub = hub ?? HubAdapter(); - /// @nodoc - @internal Future asyncWrapInSpan( String description, Future Function() execute, { String? dbName, - bool useTransactionSpan = false, + String? operation, }) async { - ISentrySpan? currentSpan = _hub.getSpan(); - if (useTransactionSpan) { - currentSpan = transactionSpan; + final parentSpan = _transactionStack.lastOrNull ?? _hub.getSpan(); + if (parentSpan == null) { + _hub.options.logger( + SentryLevel.warning, + 'Active Sentry transaction does not exist, could not start span for the Drift operation: $description', + logger: loggerName, + ); + return execute(); } - final span = currentSpan?.startChild( - SentryQueryExecutor.dbOp, + + final span = parentSpan.startChild( + operation ?? SentrySpanOperations.dbSqlQuery, description: description, ); - // ignore: invalid_use_of_internal_member - span?.origin = _origin; + span.origin = _origin; - span?.setData( - SentryQueryExecutor.dbSystemKey, - SentryQueryExecutor.dbSystem, + span.setData( + SentrySpanData.dbSystemKey, + SentrySpanData.dbSystemSqlite, ); if (dbName != null) { - span?.setData(SentryQueryExecutor.dbNameKey, dbName); + span.setData(SentrySpanData.dbNameKey, dbName); } try { final result = await execute(); - span?.status = SpanStatus.ok(); + span.status = SpanStatus.ok(); return result; } catch (exception) { - span?.throwable = exception; - span?.status = SpanStatus.internalError(); + span.throwable = exception; + span.status = SpanStatus.internalError(); rethrow; } finally { - await span?.finish(); + await span.finish(); } } - /// This span is used for the database transaction. - @internal - ISentrySpan? transactionSpan; - - /// @nodoc - @internal T beginTransaction( - String description, T Function() execute, { String? dbName, }) { - final currentSpan = _hub.getSpan(); - final span = currentSpan?.startChild( - SentryQueryExecutor.dbOp, - description: description, + final parentSpan = _transactionStack.lastOrNull ?? _hub.getSpan(); + if (parentSpan == null) { + _hub.options.logger( + SentryLevel.warning, + 'Active Sentry transaction does not exist, could not start span for Drift operation: Begin Transaction', + logger: loggerName, + ); + return execute(); + } + + final newParent = parentSpan.startChild( + SentrySpanOperations.dbSqlTransaction, + description: SentrySpanDescriptions.dbTransaction, ); - // ignore: invalid_use_of_internal_member - span?.origin = _origin; + newParent.origin = _origin; - span?.setData( - SentryQueryExecutor.dbSystemKey, - SentryQueryExecutor.dbSystem, + newParent.setData( + SentrySpanData.dbSystemKey, + SentrySpanData.dbSystemSqlite, ); if (dbName != null) { - span?.setData(SentryQueryExecutor.dbNameKey, dbName); + newParent.setData(SentrySpanData.dbNameKey, dbName); } try { final result = execute(); - span?.status = SpanStatus.unknown(); + newParent.status = SpanStatus.unknown(); + + // Only add to the stack if no error occurred + _transactionStack.add(newParent); return result; } catch (exception) { - span?.throwable = exception; - span?.status = SpanStatus.internalError(); + newParent.throwable = exception; + newParent.status = SpanStatus.internalError(); rethrow; - } finally { - transactionSpan = span; } } - /// @nodoc - @internal - Future finishTransaction( - Future Function() execute, { - String? dbName, - }) async { + Future finishTransaction(Future Function() execute) async { + final parentSpan = _transactionStack.lastOrNull; + if (parentSpan == null) { + _hub.options.logger( + SentryLevel.warning, + 'Active Sentry transaction does not exist, could not finish span for Drift operation: Finish Transaction', + logger: loggerName, + ); + return execute(); + } + try { final result = await execute(); - transactionSpan?.status = SpanStatus.ok(); + parentSpan.status = SpanStatus.ok(); return result; } catch (exception) { - transactionSpan?.throwable = exception; - transactionSpan?.status = SpanStatus.internalError(); + parentSpan.throwable = exception; + parentSpan.status = SpanStatus.internalError(); rethrow; } finally { - await transactionSpan?.finish(); - transactionSpan = null; + await parentSpan.finish(); + _transactionStack.removeLast(); } } - /// @nodoc - @internal - Future abortTransaction( - Future Function() execute, { - String? dbName, - }) async { + Future abortTransaction(Future Function() execute) async { + final parentSpan = _transactionStack.lastOrNull; + if (parentSpan == null) { + _hub.options.logger( + SentryLevel.warning, + 'Active Sentry transaction does not exist, could not finish span for Drift operation: Abort Transaction', + logger: loggerName, + ); + return Future.value(); + } + try { final result = await execute(); - transactionSpan?.status = SpanStatus.aborted(); + parentSpan.status = SpanStatus.aborted(); return result; } catch (exception) { - transactionSpan?.throwable = exception; - transactionSpan?.status = SpanStatus.internalError(); + parentSpan.throwable = exception; + parentSpan.status = SpanStatus.internalError(); rethrow; } finally { - await transactionSpan?.finish(); - transactionSpan = null; + await parentSpan.finish(); + _transactionStack.removeLast(); } } } diff --git a/drift/lib/src/sentry_transaction_executor.dart b/drift/lib/src/sentry_transaction_executor.dart deleted file mode 100644 index dba05cd8cc..0000000000 --- a/drift/lib/src/sentry_transaction_executor.dart +++ /dev/null @@ -1,167 +0,0 @@ -import 'package:drift/backends.dart'; -import 'package:meta/meta.dart'; -import 'package:sentry/sentry.dart'; - -import 'sentry_span_helper.dart'; - -/// @nodoc -@internal -class SentryTransactionExecutor extends TransactionExecutor { - final TransactionExecutor _executor; - - final Hub _hub; - - final _spanHelper = SentrySpanHelper( - // ignore: invalid_use_of_internal_member - SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - - final String? _dbName; - - bool _isOpen = false; - - final _withinTransactionDescription = 'Within transaction: '; - - /// @nodoc - SentryTransactionExecutor(this._executor, Hub hub, {@internal String? dbName}) - : _hub = hub, - _dbName = dbName { - _spanHelper.setHub(_hub); - } - - @override - TransactionExecutor beginTransaction() { - return _spanHelper.beginTransaction( - 'transaction', - () { - return _executor.beginTransaction(); - }, - dbName: _dbName, - ); - } - - @override - Future rollback() { - return _spanHelper.abortTransaction(() async { - return await _executor.rollback(); - }); - } - - @override - Future send() { - return _spanHelper.finishTransaction(() async { - return await _executor.send(); - }); - } - - @override - SqlDialect get dialect => _executor.dialect; - - @override - Future ensureOpen(QueryExecutorUser user) { - if (_isOpen) { - return Future.value(true); - } - return _spanHelper.asyncWrapInSpan( - 'Open transaction', - () async { - final res = await _executor.ensureOpen(user); - _isOpen = true; - return res; - }, - dbName: _dbName, - ); - } - - @override - Future runBatched(BatchedStatements statements) { - return _spanHelper.asyncWrapInSpan( - 'batch', - () async { - return await _executor.runBatched(statements); - }, - dbName: _dbName, - ); - } - - @override - Future runCustom(String statement, [List? args]) { - return _spanHelper.asyncWrapInSpan( - _spanDescriptionForOperations(statement), - () async { - return _executor.runCustom(statement, args); - }, - dbName: _dbName, - useTransactionSpan: true, - ); - } - - @override - Future runDelete(String statement, List args) { - return _spanHelper.asyncWrapInSpan( - _spanDescriptionForOperations(statement), - () async { - return _executor.runDelete(statement, args); - }, - dbName: _dbName, - useTransactionSpan: true, - ); - } - - @override - Future runInsert(String statement, List args) { - return _spanHelper.asyncWrapInSpan( - _spanDescriptionForOperations(statement), - () async { - return _executor.runInsert(statement, args); - }, - dbName: _dbName, - useTransactionSpan: true, - ); - } - - @override - Future>> runSelect( - String statement, - List args, - ) { - return _spanHelper.asyncWrapInSpan( - _spanDescriptionForOperations(statement), - () async { - return _executor.runSelect(statement, args); - }, - dbName: _dbName, - useTransactionSpan: true, - ); - } - - @override - // ignore: override_on_non_overriding_member, public_member_api_docs - QueryExecutor beginExclusive() { - final dynamic uncheckedExecutor = _executor; - try { - return uncheckedExecutor.beginExclusive() as QueryExecutor; - } on NoSuchMethodError catch (_) { - throw Exception('This method is not supported in Drift versions <2.19.0'); - } - } - - @override - Future runUpdate(String statement, List args) { - return _spanHelper.asyncWrapInSpan( - _spanDescriptionForOperations(statement), - () async { - return _executor.runUpdate(statement, args); - }, - dbName: _dbName, - useTransactionSpan: true, - ); - } - - @override - bool get supportsNestedTransactions => _executor.supportsNestedTransactions; - - String _spanDescriptionForOperations(String operation) { - return '$_withinTransactionDescription$operation'; - } -} diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index b6f43f54c0..c23d152d47 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.14.0'; +const String sdkVersion = '9.0.0-alpha.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 9ec3dd1c4c..d0b35f0e1d 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,12 +1,12 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 8.14.0 +version: 9.0.0-alpha.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues environment: - sdk: '>=2.17.0 <4.0.0' + sdk: '>=3.5.0 <4.0.0' platforms: android: @@ -17,9 +17,9 @@ platforms: web: dependencies: - sentry: 8.14.0 + sentry: 9.0.0-alpha.1 meta: ^1.3.0 - drift: ^2.13.0 + drift: ^2.24.0 dev_dependencies: lints: '>=2.0.0' diff --git a/drift/test/mocks/mocks.dart b/drift/test/mocks/mocks.dart index 4842f97455..98470693f6 100644 --- a/drift/test/mocks/mocks.dart +++ b/drift/test/mocks/mocks.dart @@ -5,6 +5,6 @@ import 'package:sentry/sentry.dart'; @GenerateMocks([ Hub, LazyDatabase, - TransactionExecutor, + QueryExecutor, ]) void main() {} diff --git a/drift/test/mocks/mocks.mocks.dart b/drift/test/mocks/mocks.mocks.dart index f6a88c359a..ef7ddeafde 100644 --- a/drift/test/mocks/mocks.mocks.dart +++ b/drift/test/mocks/mocks.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.5 from annotations // in sentry_drift/test/mocks/mocks.dart. // Do not manually edit this file. @@ -15,82 +15,50 @@ import 'package:sentry/src/profiling.dart' as _i4; // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class class _FakeSentryOptions_0 extends _i1.SmartFake implements _i2.SentryOptions { - _FakeSentryOptions_0( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeSentryOptions_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeSentryId_1 extends _i1.SmartFake implements _i2.SentryId { - _FakeSentryId_1( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeSentryId_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeScope_2 extends _i1.SmartFake implements _i2.Scope { - _FakeScope_2( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeScope_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeHub_3 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_3( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeHub_3(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeISentrySpan_4 extends _i1.SmartFake implements _i2.ISentrySpan { - _FakeISentrySpan_4( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeISentrySpan_4(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeQueryExecutor_5 extends _i1.SmartFake implements _i3.QueryExecutor { - _FakeQueryExecutor_5( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeQueryExecutor_5(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeTransactionExecutor_6 extends _i1.SmartFake implements _i3.TransactionExecutor { - _FakeTransactionExecutor_6( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeTransactionExecutor_6(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } /// A class which mocks [Hub]. @@ -111,35 +79,25 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.SentryOptions); @override - bool get isEnabled => (super.noSuchMethod( - Invocation.getter(#isEnabled), - returnValue: false, - ) as bool); + bool get isEnabled => + (super.noSuchMethod(Invocation.getter(#isEnabled), returnValue: false) + as bool); @override _i2.SentryId get lastEventId => (super.noSuchMethod( Invocation.getter(#lastEventId), - returnValue: _FakeSentryId_1( - this, - Invocation.getter(#lastEventId), - ), + returnValue: _FakeSentryId_1(this, Invocation.getter(#lastEventId)), ) as _i2.SentryId); @override _i2.Scope get scope => (super.noSuchMethod( Invocation.getter(#scope), - returnValue: _FakeScope_2( - this, - Invocation.getter(#scope), - ), + returnValue: _FakeScope_2(this, Invocation.getter(#scope)), ) as _i2.Scope); @override set profilerFactory(_i4.SentryProfilerFactory? value) => super.noSuchMethod( - Invocation.setter( - #profilerFactory, - value, - ), + Invocation.setter(#profilerFactory, value), returnValueForMissingStub: null, ); @@ -154,24 +112,18 @@ class MockHub extends _i1.Mock implements _i2.Hub { Invocation.method( #captureEvent, [event], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, - ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( - this, - Invocation.method( - #captureEvent, - [event], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), + returnValue: _i5.Future<_i2.SentryId>.value( + _FakeSentryId_1( + this, + Invocation.method( + #captureEvent, + [event], + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), ), - )), + ), ) as _i5.Future<_i2.SentryId>); @override @@ -185,24 +137,18 @@ class MockHub extends _i1.Mock implements _i2.Hub { Invocation.method( #captureException, [throwable], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, - ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( - this, - Invocation.method( - #captureException, - [throwable], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), + returnValue: _i5.Future<_i2.SentryId>.value( + _FakeSentryId_1( + this, + Invocation.method( + #captureException, + [throwable], + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), ), - )), + ), ) as _i5.Future<_i2.SentryId>); @override @@ -226,88 +172,79 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( - this, - Invocation.method( - #captureMessage, - [message], - { - #level: level, - #template: template, - #params: params, - #hint: hint, - #withScope: withScope, - }, + returnValue: _i5.Future<_i2.SentryId>.value( + _FakeSentryId_1( + this, + Invocation.method( + #captureMessage, + [message], + { + #level: level, + #template: template, + #params: params, + #hint: hint, + #withScope: withScope, + }, + ), ), - )), + ), ) as _i5.Future<_i2.SentryId>); @override - _i5.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => + _i5.Future<_i2.SentryId> captureFeedback( + _i2.SentryFeedback? feedback, { + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => (super.noSuchMethod( Invocation.method( - #captureUserFeedback, - [userFeedback], + #captureFeedback, + [feedback], + {#hint: hint, #withScope: withScope}, + ), + returnValue: _i5.Future<_i2.SentryId>.value( + _FakeSentryId_1( + this, + Invocation.method( + #captureFeedback, + [feedback], + {#hint: hint, #withScope: withScope}, + ), + ), ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + ) as _i5.Future<_i2.SentryId>); @override - _i5.Future addBreadcrumb( - _i2.Breadcrumb? crumb, { - _i2.Hint? hint, - }) => + _i5.Future addBreadcrumb(_i2.Breadcrumb? crumb, {_i2.Hint? hint}) => (super.noSuchMethod( - Invocation.method( - #addBreadcrumb, - [crumb], - {#hint: hint}, - ), + Invocation.method(#addBreadcrumb, [crumb], {#hint: hint}), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override void bindClient(_i2.SentryClient? client) => super.noSuchMethod( - Invocation.method( - #bindClient, - [client], - ), + Invocation.method(#bindClient, [client]), returnValueForMissingStub: null, ); @override _i2.Hub clone() => (super.noSuchMethod( - Invocation.method( - #clone, - [], - ), - returnValue: _FakeHub_3( - this, - Invocation.method( - #clone, - [], - ), - ), + Invocation.method(#clone, []), + returnValue: _FakeHub_3(this, Invocation.method(#clone, [])), ) as _i2.Hub); @override _i5.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], - ), + Invocation.method(#close, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.FutureOr configureScope(_i2.ScopeCallback? callback) => - (super.noSuchMethod(Invocation.method( - #configureScope, - [callback], - )) as _i5.FutureOr); + (super.noSuchMethod(Invocation.method(#configureScope, [callback])) + as _i5.FutureOr); @override _i2.ISentrySpan startTransaction( @@ -325,10 +262,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { (super.noSuchMethod( Invocation.method( #startTransaction, - [ - name, - operation, - ], + [name, operation], { #description: description, #startTimestamp: startTimestamp, @@ -344,10 +278,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { this, Invocation.method( #startTransaction, - [ - name, - operation, - ], + [name, operation], { #description: description, #startTimestamp: startTimestamp, @@ -409,21 +340,24 @@ class MockHub extends _i1.Mock implements _i2.Hub { _i5.Future<_i2.SentryId> captureTransaction( _i2.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, - ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( - this, - Invocation.method( - #captureTransaction, - [transaction], - {#traceContext: traceContext}, + {#traceContext: traceContext, #hint: hint}, + ), + returnValue: _i5.Future<_i2.SentryId>.value( + _FakeSentryId_1( + this, + Invocation.method( + #captureTransaction, + [transaction], + {#traceContext: traceContext, #hint: hint}, + ), ), - )), + ), ) as _i5.Future<_i2.SentryId>); @override @@ -433,14 +367,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { String? transaction, ) => super.noSuchMethod( - Invocation.method( - #setSpanContext, - [ - throwable, - span, - transaction, - ], - ), + Invocation.method(#setSpanContext, [throwable, span, transaction]), returnValueForMissingStub: null, ); } @@ -456,11 +383,9 @@ class MockLazyDatabase extends _i1.Mock implements _i6.LazyDatabase { @override _i6.DatabaseOpener get opener => (super.noSuchMethod( Invocation.getter(#opener), - returnValue: () => - _i5.Future<_i3.QueryExecutor>.value(_FakeQueryExecutor_5( - this, - Invocation.getter(#opener), - )), + returnValue: () => _i5.Future<_i3.QueryExecutor>.value( + _FakeQueryExecutor_5(this, Invocation.getter(#opener)), + ), ) as _i6.DatabaseOpener); @override @@ -470,87 +395,57 @@ class MockLazyDatabase extends _i1.Mock implements _i6.LazyDatabase { ) as _i3.SqlDialect); @override - _i3.TransactionExecutor beginTransaction() => (super.noSuchMethod( - Invocation.method( - #beginTransaction, - [], + _i3.QueryExecutor beginExclusive() => (super.noSuchMethod( + Invocation.method(#beginExclusive, []), + returnValue: _FakeQueryExecutor_5( + this, + Invocation.method(#beginExclusive, []), ), + ) as _i3.QueryExecutor); + + @override + _i3.TransactionExecutor beginTransaction() => (super.noSuchMethod( + Invocation.method(#beginTransaction, []), returnValue: _FakeTransactionExecutor_6( this, - Invocation.method( - #beginTransaction, - [], - ), + Invocation.method(#beginTransaction, []), ), ) as _i3.TransactionExecutor); @override _i5.Future ensureOpen(_i3.QueryExecutorUser? user) => (super.noSuchMethod( - Invocation.method( - #ensureOpen, - [user], - ), + Invocation.method(#ensureOpen, [user]), returnValue: _i5.Future.value(false), ) as _i5.Future); @override _i5.Future runBatched(_i3.BatchedStatements? statements) => (super.noSuchMethod( - Invocation.method( - #runBatched, - [statements], - ), + Invocation.method(#runBatched, [statements]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override - _i5.Future runCustom( - String? statement, [ - List? args, - ]) => + _i5.Future runCustom(String? statement, [List? args]) => (super.noSuchMethod( - Invocation.method( - #runCustom, - [ - statement, - args, - ], - ), + Invocation.method(#runCustom, [statement, args]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override - _i5.Future runDelete( - String? statement, - List? args, - ) => + _i5.Future runDelete(String? statement, List? args) => (super.noSuchMethod( - Invocation.method( - #runDelete, - [ - statement, - args, - ], - ), + Invocation.method(#runDelete, [statement, args]), returnValue: _i5.Future.value(0), ) as _i5.Future); @override - _i5.Future runInsert( - String? statement, - List? args, - ) => + _i5.Future runInsert(String? statement, List? args) => (super.noSuchMethod( - Invocation.method( - #runInsert, - [ - statement, - args, - ], - ), + Invocation.method(#runInsert, [statement, args]), returnValue: _i5.Future.value(0), ) as _i5.Future); @@ -560,92 +455,45 @@ class MockLazyDatabase extends _i1.Mock implements _i6.LazyDatabase { List? args, ) => (super.noSuchMethod( - Invocation.method( - #runSelect, - [ - statement, - args, - ], - ), + Invocation.method(#runSelect, [statement, args]), returnValue: _i5.Future>>.value( - >[]), + >[], + ), ) as _i5.Future>>); @override - _i5.Future runUpdate( - String? statement, - List? args, - ) => + _i5.Future runUpdate(String? statement, List? args) => (super.noSuchMethod( - Invocation.method( - #runUpdate, - [ - statement, - args, - ], - ), + Invocation.method(#runUpdate, [statement, args]), returnValue: _i5.Future.value(0), ) as _i5.Future); @override _i5.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], - ), + Invocation.method(#close, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); } -/// A class which mocks [TransactionExecutor]. +/// A class which mocks [QueryExecutor]. /// /// See the documentation for Mockito's code generation for more information. -class MockTransactionExecutor extends _i1.Mock - implements _i3.TransactionExecutor { - MockTransactionExecutor() { +class MockQueryExecutor extends _i1.Mock implements _i3.QueryExecutor { + MockQueryExecutor() { _i1.throwOnMissingStub(this); } - @override - bool get supportsNestedTransactions => (super.noSuchMethod( - Invocation.getter(#supportsNestedTransactions), - returnValue: false, - ) as bool); - @override _i3.SqlDialect get dialect => (super.noSuchMethod( Invocation.getter(#dialect), returnValue: _i3.SqlDialect.sqlite, ) as _i3.SqlDialect); - @override - _i5.Future send() => (super.noSuchMethod( - Invocation.method( - #send, - [], - ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); - - @override - _i5.Future rollback() => (super.noSuchMethod( - Invocation.method( - #rollback, - [], - ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); - @override _i5.Future ensureOpen(_i3.QueryExecutorUser? user) => (super.noSuchMethod( - Invocation.method( - #ensureOpen, - [user], - ), + Invocation.method(#ensureOpen, [user]), returnValue: _i5.Future.value(false), ) as _i5.Future); @@ -655,78 +503,37 @@ class MockTransactionExecutor extends _i1.Mock List? args, ) => (super.noSuchMethod( - Invocation.method( - #runSelect, - [ - statement, - args, - ], - ), + Invocation.method(#runSelect, [statement, args]), returnValue: _i5.Future>>.value( - >[]), + >[], + ), ) as _i5.Future>>); @override - _i5.Future runInsert( - String? statement, - List? args, - ) => + _i5.Future runInsert(String? statement, List? args) => (super.noSuchMethod( - Invocation.method( - #runInsert, - [ - statement, - args, - ], - ), + Invocation.method(#runInsert, [statement, args]), returnValue: _i5.Future.value(0), ) as _i5.Future); @override - _i5.Future runUpdate( - String? statement, - List? args, - ) => + _i5.Future runUpdate(String? statement, List? args) => (super.noSuchMethod( - Invocation.method( - #runUpdate, - [ - statement, - args, - ], - ), + Invocation.method(#runUpdate, [statement, args]), returnValue: _i5.Future.value(0), ) as _i5.Future); @override - _i5.Future runDelete( - String? statement, - List? args, - ) => + _i5.Future runDelete(String? statement, List? args) => (super.noSuchMethod( - Invocation.method( - #runDelete, - [ - statement, - args, - ], - ), + Invocation.method(#runDelete, [statement, args]), returnValue: _i5.Future.value(0), ) as _i5.Future); @override - _i5.Future runCustom( - String? statement, [ - List? args, - ]) => + _i5.Future runCustom(String? statement, [List? args]) => (super.noSuchMethod( - Invocation.method( - #runCustom, - [ - statement, - args, - ], - ), + Invocation.method(#runCustom, [statement, args]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @@ -734,35 +541,32 @@ class MockTransactionExecutor extends _i1.Mock @override _i5.Future runBatched(_i3.BatchedStatements? statements) => (super.noSuchMethod( - Invocation.method( - #runBatched, - [statements], - ), + Invocation.method(#runBatched, [statements]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i3.TransactionExecutor beginTransaction() => (super.noSuchMethod( - Invocation.method( - #beginTransaction, - [], - ), + Invocation.method(#beginTransaction, []), returnValue: _FakeTransactionExecutor_6( this, - Invocation.method( - #beginTransaction, - [], - ), + Invocation.method(#beginTransaction, []), ), ) as _i3.TransactionExecutor); @override - _i5.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], + _i3.QueryExecutor beginExclusive() => (super.noSuchMethod( + Invocation.method(#beginExclusive, []), + returnValue: _FakeQueryExecutor_5( + this, + Invocation.method(#beginExclusive, []), ), + ) as _i3.QueryExecutor); + + @override + _i5.Future close() => (super.noSuchMethod( + Invocation.method(#close, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); diff --git a/drift/test/sentry_database_test.dart b/drift/test/sentry_database_test.dart deleted file mode 100644 index 1e3e2768a0..0000000000 --- a/drift/test/sentry_database_test.dart +++ /dev/null @@ -1,689 +0,0 @@ -// ignore_for_file: invalid_use_of_internal_member, library_annotations, deprecated_member_use_from_same_package - -@TestOn('vm') - -import 'package:drift/drift.dart'; -import 'package:drift/native.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; -import 'package:sentry/sentry.dart'; -import 'package:sentry/src/sentry_tracer.dart'; -import 'package:sentry_drift/src/sentry_query_executor.dart'; -import 'package:sentry_drift/src/sentry_transaction_executor.dart'; -import 'package:sentry_drift/src/version.dart'; -import 'package:sqlite3/open.dart'; - -import 'mocks/mocks.mocks.dart'; -import 'test_database.dart'; -import 'utils.dart'; -import 'utils/windows_helper.dart'; - -void main() { - open.overrideFor(OperatingSystem.windows, openOnWindows); - - final expectedInsertStatement = - 'INSERT INTO "todo_items" ("title", "body") VALUES (?, ?)'; - final expectedUpdateStatement = - 'UPDATE "todo_items" SET "title" = ?, "body" = ? WHERE "title" = ?;'; - final expectedSelectStatement = 'SELECT * FROM todo_items'; - final expectedDeleteStatement = 'DELETE FROM "todo_items";'; - final expectedCloseStatement = 'Close DB: ${Fixture.dbName}'; - final expectedOpenStatement = 'Open DB: ${Fixture.dbName}'; - final expectedTransactionStatement = 'transaction'; - final withinTransactionDescription = 'Within transaction: '; - - void verifySpan( - String description, - SentrySpan? span, { - String origin = SentryTraceOrigins.autoDbDriftQueryExecutor, - SpanStatus? status, - }) { - status ??= SpanStatus.ok(); - expect(span?.context.operation, SentryQueryExecutor.dbOp); - expect(span?.context.description, description); - expect(span?.status, status); - expect(span?.origin, origin); - expect( - span?.data[SentryQueryExecutor.dbSystemKey], - SentryQueryExecutor.dbSystem, - ); - expect( - span?.data[SentryQueryExecutor.dbNameKey], - Fixture.dbName, - ); - } - - void verifyErrorSpan( - String description, - Exception exception, - SentrySpan? span, { - String origin = SentryTraceOrigins.autoDbDriftQueryExecutor, - }) { - expect(span?.context.operation, SentryQueryExecutor.dbOp); - expect(span?.context.description, description); - expect(span?.status, SpanStatus.internalError()); - expect(span?.origin, origin); - expect( - span?.data[SentryQueryExecutor.dbSystemKey], - SentryQueryExecutor.dbSystem, - ); - expect( - span?.data[SentryQueryExecutor.dbNameKey], - Fixture.dbName, - ); - - expect(span?.throwable, exception); - } - - Future insertRow(AppDatabase sut, {bool withError = false}) { - if (withError) { - return sut.into(sut.todoItems).insert( - TodoItemsCompanion.insert( - title: '', - content: '', - ), - ); - } else { - return sut.into(sut.todoItems).insert( - TodoItemsCompanion.insert( - title: 'todo: finish drift setup', - content: 'We can now write queries and define our own tables.', - ), - ); - } - } - - Future updateRow(AppDatabase sut, {bool withError = false}) { - if (withError) { - return (sut.update(sut.todoItems) - ..where((tbl) => tbl.title.equals('doesnt exist'))) - .write( - TodoItemsCompanion( - title: Value('after update'), - content: Value('We can now write queries and define our own tables.'), - ), - ); - } else { - return (sut.update(sut.todoItems) - ..where((tbl) => tbl.title.equals('todo: finish drift setup'))) - .write( - TodoItemsCompanion( - title: Value('after update'), - content: Value('We can now write queries and define our own tables.'), - ), - ); - } - } - - group('adds span', () { - late Fixture fixture; - - setUp(() async { - fixture = Fixture(); - - when(fixture.hub.options).thenReturn(fixture.options); - when(fixture.hub.getSpan()).thenReturn(fixture.tracer); - - await fixture.setUp(); - }); - - tearDown(() async { - await fixture.tearDown(); - }); - - test('open span is only added once', () async { - final sut = fixture.sut; - - await insertRow(sut); - await insertRow(sut); - await insertRow(sut); - - final openSpansCount = fixture.tracer.children - .where( - (element) => element.context.description == expectedOpenStatement, - ) - .length; - - expect(openSpansCount, 1); - }); - - test('insert adds span', () async { - final sut = fixture.sut; - - await insertRow(sut); - - verifySpan( - expectedInsertStatement, - fixture.getCreatedSpan(), - ); - }); - - test('update adds span', () async { - final sut = fixture.sut; - - await insertRow(sut); - await updateRow(sut); - - verifySpan( - expectedUpdateStatement, - fixture.getCreatedSpan(), - ); - }); - - test('custom adds span', () async { - final sut = fixture.sut; - - await sut.customStatement('SELECT * FROM todo_items'); - - verifySpan( - expectedSelectStatement, - fixture.getCreatedSpan(), - ); - }); - - test('delete adds span', () async { - final sut = fixture.sut; - - await insertRow(sut); - await fixture.sut.delete(fixture.sut.todoItems).go(); - - verifySpan( - expectedDeleteStatement, - fixture.getCreatedSpan(), - ); - }); - - test('transaction adds insert spans', () async { - final sut = fixture.sut; - - await sut.transaction(() async { - await insertRow(sut); - await insertRow(sut); - }); - - final insertSpanCount = fixture.tracer.children - .where( - (element) => - element.context.description == - '$withinTransactionDescription$expectedInsertStatement', - ) - .length; - expect(insertSpanCount, 2); - - verifySpan( - '$withinTransactionDescription$expectedInsertStatement', - fixture.getCreatedSpan(), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - - verifySpan( - expectedTransactionStatement, - fixture.getCreatedSpanByDescription(expectedTransactionStatement), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - }); - - test('transaction adds update spans', () async { - final sut = fixture.sut; - - await sut.transaction(() async { - await insertRow(sut); - await updateRow(sut); - }); - - final updateSpanCount = fixture.tracer.children - .where( - (element) => - element.context.description == - '$withinTransactionDescription$expectedUpdateStatement', - ) - .length; - expect(updateSpanCount, 1); - - verifySpan( - '$withinTransactionDescription$expectedUpdateStatement', - fixture.getCreatedSpan(), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - - verifySpan( - expectedTransactionStatement, - fixture.getCreatedSpanByDescription(expectedTransactionStatement), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - }); - - test('transaction adds delete spans', () async { - final sut = fixture.sut; - - await sut.transaction(() async { - await insertRow(sut); - await fixture.sut.delete(fixture.sut.todoItems).go(); - }); - - final deleteSpanCount = fixture.tracer.children - .where( - (element) => - element.context.description == - '$withinTransactionDescription$expectedDeleteStatement', - ) - .length; - expect(deleteSpanCount, 1); - - verifySpan( - '$withinTransactionDescription$expectedDeleteStatement', - fixture.getCreatedSpan(), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - - verifySpan( - expectedTransactionStatement, - fixture.getCreatedSpanByDescription(expectedTransactionStatement), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - }); - - test('transaction adds custom spans', () async { - final sut = fixture.sut; - - await sut.transaction(() async { - await insertRow(sut); - await sut.customStatement('SELECT * FROM todo_items'); - }); - - final customSpanCount = fixture.tracer.children - .where( - (element) => - element.context.description == - '$withinTransactionDescription$expectedSelectStatement', - ) - .length; - expect(customSpanCount, 1); - - verifySpan( - '$withinTransactionDescription$expectedSelectStatement', - fixture.getCreatedSpan(), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - - verifySpan( - expectedTransactionStatement, - fixture.getCreatedSpanByDescription(expectedTransactionStatement), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - }); - - test('transaction rollback adds span', () async { - final sut = fixture.sut; - - await insertRow(sut); - await insertRow(sut); - - try { - await sut.transaction(() async { - await insertRow(sut, withError: true); - }); - } catch (_) {} - - final spans = fixture.tracer.children - .where((child) => child.status == SpanStatus.aborted()); - expect(spans.length, 1); - final abortedSpan = spans.first; - - verifySpan( - expectedTransactionStatement, - abortedSpan, - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - status: SpanStatus.aborted(), - ); - }); - - test('batch adds span', () async { - final sut = fixture.sut; - - await sut.batch((batch) async { - await insertRow(sut); - await insertRow(sut); - }); - - verifySpan( - 'batch', - fixture.getCreatedSpan(), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - }); - - test('close adds span', () async { - final sut = fixture.sut; - - await sut.close(); - - verifySpan( - 'Close DB: ${Fixture.dbName}', - fixture.getCreatedSpan(), - ); - }); - - test('open adds span', () async { - final sut = fixture.sut; - - // SentryDriftDatabase is by default lazily opened by default so it won't - // create a span until it is actually used. - await sut.select(sut.todoItems).get(); - - verifySpan( - expectedOpenStatement, - fixture.getCreatedSpanByDescription(expectedOpenStatement), - ); - }); - }); - - group('does not add span', () { - late Fixture fixture; - - setUp(() async { - fixture = Fixture(); - - when(fixture.hub.options).thenReturn(fixture.options); - when(fixture.hub.getSpan()).thenReturn(fixture.tracer); - - await fixture.setUp(); - }); - - tearDown(() async { - await fixture.tearDown(); - }); - - test('does not add open span if db is not used', () async { - fixture.sut; - - expect(fixture.tracer.children.isEmpty, true); - }); - - test('batch does not add span for failed operations', () async { - final sut = fixture.sut; - - try { - await sut.batch((batch) async { - await insertRow(sut, withError: true); - await insertRow(sut); - }); - } catch (_) {} - - expect(fixture.tracer.children.isEmpty, true); - }); - }); - - group('adds error span', () { - late Fixture fixture; - - setUp(() async { - fixture = Fixture(); - - when(fixture.hub.options).thenReturn(fixture.options); - when(fixture.hub.getSpan()).thenReturn(fixture.tracer); - when(fixture.mockLazyDatabase.ensureOpen(any)) - .thenAnswer((_) => Future.value(true)); - - await fixture.setUp(injectMock: true); - }); - - tearDown(() async { - await fixture.tearDown(); - }); - - test('throwing runInsert throws error span', () async { - when(fixture.mockLazyDatabase.runInsert(any, any)) - .thenThrow(fixture.exception); - - try { - await insertRow(fixture.sut); - } catch (exception) { - expect(exception, fixture.exception); - } - - verifyErrorSpan( - expectedInsertStatement, - fixture.exception, - fixture.getCreatedSpan(), - ); - }); - - test('throwing runUpdate throws error span', () async { - when(fixture.mockLazyDatabase.runUpdate(any, any)) - .thenThrow(fixture.exception); - - try { - await updateRow(fixture.sut); - } catch (exception) { - expect(exception, fixture.exception); - } - - verifyErrorSpan( - expectedUpdateStatement, - fixture.exception, - fixture.getCreatedSpan(), - ); - }); - - test('throwing runCustom throws error span', () async { - when(fixture.mockLazyDatabase.runCustom(any, any)) - .thenThrow(fixture.exception); - - try { - await fixture.sut.customStatement('SELECT * FROM todo_items'); - } catch (exception) { - expect(exception, fixture.exception); - } - - verifyErrorSpan( - expectedSelectStatement, - fixture.exception, - fixture.getCreatedSpan(), - ); - }); - - test('throwing transaction throws error span', () async { - final mockTransactionExecutor = MockTransactionExecutor(); - when(mockTransactionExecutor.beginTransaction()) - .thenThrow(fixture.exception); - - try { - // We need to move it inside the try/catch becaue SentryTransactionExecutor - // starts beginTransaction() directly after init - final SentryTransactionExecutor transactionExecutor = - SentryTransactionExecutor( - mockTransactionExecutor, - fixture.hub, - dbName: Fixture.dbName, - ); - - when(fixture.mockLazyDatabase.beginTransaction()) - .thenReturn(transactionExecutor); - - await fixture.sut.transaction(() async { - await insertRow(fixture.sut); - }); - } catch (exception) { - expect(exception, fixture.exception); - } - - verifyErrorSpan( - expectedTransactionStatement, - fixture.exception, - fixture.getCreatedSpan(), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - }); - - test('throwing batch throws error span', () async { - final mockTransactionExecutor = MockTransactionExecutor(); - when(mockTransactionExecutor.beginTransaction()) - .thenThrow(fixture.exception); - - // We need to move it inside the try/catch becaue SentryTransactionExecutor - // starts beginTransaction() directly after init - final SentryTransactionExecutor transactionExecutor = - SentryTransactionExecutor( - mockTransactionExecutor, - fixture.hub, - dbName: Fixture.dbName, - ); - - when(fixture.mockLazyDatabase.beginTransaction()) - .thenReturn(transactionExecutor); - - when(fixture.mockLazyDatabase.runInsert(any, any)) - .thenAnswer((realInvocation) => Future.value(1)); - - try { - await fixture.sut.batch((batch) async { - await insertRow(fixture.sut); - }); - } catch (exception) { - expect(exception, fixture.exception); - } - - verifyErrorSpan( - expectedTransactionStatement, - fixture.exception, - fixture.getCreatedSpan(), - origin: SentryTraceOrigins.autoDbDriftTransactionExecutor, - ); - }); - - test('throwing close throws error span', () async { - when(fixture.mockLazyDatabase.close()).thenThrow(fixture.exception); - when(fixture.mockLazyDatabase.runInsert(any, any)) - .thenAnswer((_) => Future.value(1)); - - try { - await insertRow(fixture.sut); - await fixture.sut.close(); - } catch (exception) { - expect(exception, fixture.exception); - } - - verifyErrorSpan( - expectedCloseStatement, - fixture.exception, - fixture.getCreatedSpan(), - ); - - when(fixture.mockLazyDatabase.close()).thenAnswer((_) => Future.value()); - }); - - test('throwing ensureOpen throws error span', () async { - when(fixture.mockLazyDatabase.ensureOpen(any)) - .thenThrow(fixture.exception); - - try { - await fixture.sut.select(fixture.sut.todoItems).get(); - } catch (exception) { - expect(exception, fixture.exception); - } - - verifyErrorSpan( - expectedOpenStatement, - fixture.exception, - fixture.getCreatedSpanByDescription(expectedOpenStatement), - ); - }); - - test('throwing runDelete throws error span', () async { - when(fixture.mockLazyDatabase.runDelete(any, any)) - .thenThrow(fixture.exception); - - try { - await fixture.sut.delete(fixture.sut.todoItems).go(); - } catch (exception) { - expect(exception, fixture.exception); - } - - verifyErrorSpan( - expectedDeleteStatement, - fixture.exception, - fixture.getCreatedSpan(), - ); - }); - }); - - group('integrations', () { - late Fixture fixture; - - setUp(() async { - fixture = Fixture(); - - when(fixture.hub.options).thenReturn(fixture.options); - when(fixture.hub.getSpan()).thenReturn(fixture.tracer); - - await fixture.setUp(); - }); - - tearDown(() async { - await fixture.tearDown(); - }); - - test('adds integration', () { - expect( - fixture.options.sdk.integrations.contains('SentryDriftTracing'), - true, - ); - }); - - test('adds package', () { - expect( - fixture.options.sdk.packages.any( - (element) => - element.name == packageName && element.version == sdkVersion, - ), - true, - ); - }); - }); -} - -class Fixture { - final options = defaultTestOptions(); - final hub = MockHub(); - static final dbName = 'people-drift-impl'; - final exception = Exception('fixture-exception'); - final _context = SentryTransactionContext('name', 'operation'); - late final tracer = SentryTracer(_context, hub); - late AppDatabase sut; - final mockLazyDatabase = MockLazyDatabase(); - - Future setUp({bool injectMock = false}) async { - sut = AppDatabase(openConnection(injectMock: injectMock)); - } - - Future tearDown() async { - await sut.close(); - } - - SentrySpan? getCreatedSpan() { - return tracer.children.last; - } - - SentrySpan? getCreatedSpanByDescription(String description) { - return tracer.children - .firstWhere((element) => element.context.description == description); - } - - SentryQueryExecutor openConnection({bool injectMock = false}) { - if (injectMock) { - final executor = - SentryQueryExecutor(() => mockLazyDatabase, databaseName: dbName); - executor.setHub(hub); - return executor; - } else { - return SentryQueryExecutor( - () { - return NativeDatabase.memory(); - }, - hub: hub, - databaseName: dbName, - ); - } - } -} diff --git a/drift/test/sentry_drift_test.dart b/drift/test/sentry_drift_test.dart new file mode 100644 index 0000000000..fbf42c43de --- /dev/null +++ b/drift/test/sentry_drift_test.dart @@ -0,0 +1,802 @@ +// ignore_for_file: invalid_use_of_internal_member, library_annotations + +@TestOn('vm') + +import 'package:drift/drift.dart'; +import 'package:drift/native.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; +import 'package:sentry/sentry.dart'; +import 'package:sentry/src/sentry_tracer.dart'; +import 'package:sentry_drift/src/constants.dart' as drift_constants; +import 'package:sentry_drift/src/sentry_query_interceptor.dart'; +import 'package:sentry_drift/src/version.dart'; +import 'package:sqlite3/open.dart'; + +import 'mocks/mocks.mocks.dart'; +import 'test_database.dart'; +import 'utils.dart'; +import 'utils/windows_helper.dart'; + +void main() { + open.overrideFor(OperatingSystem.windows, openOnWindows); + + final expectedInsertStatement = + 'INSERT INTO "todo_items" ("title", "body") VALUES (?, ?)'; + final expectedUpdateStatement = + 'UPDATE "todo_items" SET "title" = ?, "body" = ? WHERE "title" = ?;'; + final expectedSelectStatement = 'SELECT * FROM "todo_items";'; + final expectedDeleteStatement = 'DELETE FROM "todo_items";'; + + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + await Sentry.init( + (options) {}, + options: fixture.options, + ); + }); + + group('open operations', () { + test('successful adds span only once', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await _insertRow(db); + await _insertRow(db); + await _insertRow(db); + + final openSpans = tx.children.where( + (element) => + element.context.description == + SentrySpanDescriptions.dbOpen(dbName: Fixture.dbName), + ); + + expect(openSpans.length, 1); + _verifySpan( + operation: SentrySpanOperations.dbOpen, + SentrySpanDescriptions.dbOpen(dbName: Fixture.dbName), + openSpans.first, + ); + }); + + test('error case adds error span', () async { + final exception = Exception('test'); + final queryExecutor = MockQueryExecutor(); + when(queryExecutor.ensureOpen(any)).thenThrow(exception); + when(queryExecutor.runInsert(any, any)) + .thenAnswer((_) => Future.value(1)); + when(queryExecutor.dialect).thenReturn(SqlDialect.sqlite); + + final sut = fixture.getSut(); + final db = AppDatabase(queryExecutor.interceptWith(sut)); + + final tx = _startTransaction(); + try { + await _insertRow(db); + } catch (e) { + // making sure the thrown exception doesn't fail the test + } + + final openSpans = tx.children.where( + (element) => + element.context.description == + SentrySpanDescriptions.dbOpen(dbName: Fixture.dbName), + ); + + expect(openSpans.length, 1); + _verifyErrorSpan( + operation: SentrySpanOperations.dbOpen, + SentrySpanDescriptions.dbOpen(dbName: Fixture.dbName), + exception, + openSpans.first, + ); + }); + }); + + group('close operations', () { + test('successful adds close only once', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await _insertRow(db); + await db.close(); + + final closeSpans = tx.children.where( + (element) => + element.context.description == + SentrySpanDescriptions.dbClose(dbName: Fixture.dbName), + ); + + expect(closeSpans.length, 1); + _verifySpan( + operation: SentrySpanOperations.dbClose, + SentrySpanDescriptions.dbClose(dbName: Fixture.dbName), + closeSpans.first, + ); + }); + + test('error case adds error span', () async { + final exception = Exception('test'); + final queryExecutor = MockQueryExecutor(); + when(queryExecutor.ensureOpen(any)).thenAnswer((_) => Future.value(true)); + when(queryExecutor.runInsert(any, any)) + .thenAnswer((_) => Future.value(1)); + when(queryExecutor.close()).thenThrow(exception); + when(queryExecutor.dialect).thenReturn(SqlDialect.sqlite); + + final sut = fixture.getSut(); + final db = AppDatabase(queryExecutor.interceptWith(sut)); + + final tx = _startTransaction(); + try { + await _insertRow(db); + await db.close(); + } catch (e) { + // making sure the thrown exception doesn't fail the test + } + + final closeSpans = tx.children.where( + (element) => + element.context.description == + SentrySpanDescriptions.dbClose(dbName: Fixture.dbName), + ); + + expect(closeSpans.length, 1); + _verifyErrorSpan( + SentrySpanDescriptions.dbClose(dbName: Fixture.dbName), + exception, + closeSpans.first, + operation: SentrySpanOperations.dbClose, + ); + }); + }); + + group('insert operations', () { + test('successful adds span', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await _insertRow(db); + + _verifySpan( + expectedInsertStatement, + tx.children.last, + ); + }); + + test('error case adds error span', () async { + final exception = Exception('test'); + final queryExecutor = MockQueryExecutor(); + when(queryExecutor.ensureOpen(any)).thenAnswer((_) => Future.value(true)); + when(queryExecutor.runInsert(any, any)).thenThrow(exception); + when(queryExecutor.dialect).thenReturn(SqlDialect.sqlite); + + final sut = fixture.getSut(); + final db = AppDatabase(queryExecutor.interceptWith(sut)); + + final tx = _startTransaction(); + try { + await _insertRow(db); + } catch (e) { + // making sure the thrown exception doesn't fail the test + } + + _verifyErrorSpan( + expectedInsertStatement, + exception, + tx.children.last, + ); + }); + }); + + group('update operations', () { + test('successful adds span', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await _insertRow(db); + await _updateRow(db); + + _verifySpan( + expectedUpdateStatement, + tx.children.last, + ); + }); + + test('error case adds error span', () async { + final exception = Exception('test'); + final queryExecutor = MockQueryExecutor(); + when(queryExecutor.ensureOpen(any)).thenAnswer((_) => Future.value(true)); + when(queryExecutor.runInsert(any, any)) + .thenAnswer((_) => Future.value(1)); + when(queryExecutor.runUpdate(any, any)).thenThrow(exception); + when(queryExecutor.dialect).thenReturn(SqlDialect.sqlite); + + final sut = fixture.getSut(); + final db = AppDatabase(queryExecutor.interceptWith(sut)); + + final tx = _startTransaction(); + try { + await _insertRow(db); + await _updateRow(db); + } catch (e) { + // making sure the thrown exception doesn't fail the test + } + + _verifyErrorSpan( + expectedUpdateStatement, + exception, + tx.children.last, + ); + }); + }); + + group('delete operations', () { + test('successful adds span', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await _insertRow(db); + await db.delete(db.todoItems).go(); + + _verifySpan( + expectedDeleteStatement, + tx.children.last, + ); + }); + + test('error case adds error span', () async { + final exception = Exception('test'); + final queryExecutor = MockQueryExecutor(); + when(queryExecutor.ensureOpen(any)).thenAnswer((_) => Future.value(true)); + when(queryExecutor.runInsert(any, any)) + .thenAnswer((_) => Future.value(1)); + when(queryExecutor.runDelete(any, any)).thenThrow(exception); + when(queryExecutor.dialect).thenReturn(SqlDialect.sqlite); + + final sut = fixture.getSut(); + final db = AppDatabase(queryExecutor.interceptWith(sut)); + + final tx = _startTransaction(); + try { + await _insertRow(db); + await db.delete(db.todoItems).go(); + } catch (e) { + // making sure the thrown exception doesn't fail the test + } + + _verifyErrorSpan( + expectedDeleteStatement, + exception, + tx.children.last, + ); + }); + }); + + group('select operations', () { + test('successful adds span', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await _insertRow(db); + await db.select(db.todoItems).get(); + + _verifySpan( + expectedSelectStatement, + tx.children.last, + ); + }); + + test('error case adds error span', () async { + final exception = Exception('test'); + final queryExecutor = MockQueryExecutor(); + when(queryExecutor.ensureOpen(any)).thenAnswer((_) => Future.value(true)); + when(queryExecutor.runInsert(any, any)) + .thenAnswer((_) => Future.value(1)); + when(queryExecutor.runSelect(any, any)).thenThrow(exception); + when(queryExecutor.dialect).thenReturn(SqlDialect.sqlite); + + final sut = fixture.getSut(); + final db = AppDatabase(queryExecutor.interceptWith(sut)); + + final tx = _startTransaction(); + try { + await _insertRow(db); + await db.select(db.todoItems).get(); + } catch (e) { + // making sure the thrown exception doesn't fail the test + } + + _verifyErrorSpan( + expectedSelectStatement, + exception, + tx.children.last, + ); + }); + }); + + group('custom query operations', () { + test('successful adds span', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await db.customStatement(expectedSelectStatement); + + _verifySpan( + expectedSelectStatement, + tx.children.last, + ); + }); + + test('error case adds error span', () async { + final exception = Exception('test'); + final queryExecutor = MockQueryExecutor(); + when(queryExecutor.ensureOpen(any)).thenAnswer((_) => Future.value(true)); + when(queryExecutor.runCustom(any, any)).thenThrow(exception); + when(queryExecutor.dialect).thenReturn(SqlDialect.sqlite); + + final sut = fixture.getSut(); + final db = AppDatabase(queryExecutor.interceptWith(sut)); + + final tx = _startTransaction(); + try { + await db.customStatement(expectedSelectStatement); + } catch (e) { + // making sure the thrown exception doesn't fail the test + } + + _verifyErrorSpan( + expectedSelectStatement, + exception, + tx.children.last, + ); + }); + }); + + group('transaction operations', () { + test('without transaction, spans are added to active scope span', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await _insertRow(db); + + expect(tx.children.length, 2); + + final insertSpan = tx.children.last; + expect(insertSpan.context.parentSpanId, tx.context.spanId); + expect(sut.spanHelper.transactionStack, isEmpty); + }); + + // already tests nesting + test('commit successful adds spans', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await db.transaction(() async { + await db.into(db.todoItems).insert( + TodoItemsCompanion.insert( + title: 'first transaction insert', + content: 'test', + ), + ); + await db.transaction(() async { + await db.delete(db.todoItems).go(); + }); + }); + + // 5 spans = 1 db open + 2 tx + 1 insert + 1 delete + expect(tx.children.length, 5); + + final outerTxSpan = tx.children[1]; + final insertSpan = tx.children[2]; + final innerTxSpan = tx.children[3]; + final deleteSpan = tx.children[4]; + + // Verify parent relationships + expect(outerTxSpan.context.parentSpanId, tx.context.spanId); + expect(insertSpan.context.parentSpanId, outerTxSpan.context.spanId); + expect(innerTxSpan.context.parentSpanId, outerTxSpan.context.spanId); + expect(deleteSpan.context.parentSpanId, innerTxSpan.context.spanId); + }); + + test('successful commit adds insert spans', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await db.transaction(() async { + await _insertRow(db); + await _insertRow(db); + }); + + final insertSpanCount = tx.children + .where( + (element) => element.context.description == expectedInsertStatement, + ) + .length; + expect(insertSpanCount, 2); + + _verifySpan( + expectedInsertStatement, + tx.children.last, + ); + + _verifySpan( + SentrySpanDescriptions.dbTransaction, + tx.children[1], + operation: SentrySpanOperations.dbSqlTransaction, + ); + }); + + test('successful commit adds update spans', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await db.transaction(() async { + await _insertRow(db); + await _updateRow(db); + }); + + final insertSpanCount = tx.children + .where( + (element) => element.context.description == expectedInsertStatement, + ) + .length; + expect(insertSpanCount, 1); + + final updateSpanCount = tx.children + .where( + (element) => element.context.description == expectedInsertStatement, + ) + .length; + expect(updateSpanCount, 1); + + _verifySpan( + expectedUpdateStatement, + tx.children.last, + ); + + _verifySpan( + SentrySpanDescriptions.dbTransaction, + tx.children[1], + operation: SentrySpanOperations.dbSqlTransaction, + ); + }); + + test('successful commit adds delete spans', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await db.transaction(() async { + await _insertRow(db); + await db.delete(db.todoItems).go(); + }); + + final insertSpanCount = tx.children + .where( + (element) => element.context.description == expectedInsertStatement, + ) + .length; + expect(insertSpanCount, 1); + + final deleteSpanCount = tx.children + .where( + (element) => element.context.description == expectedDeleteStatement, + ) + .length; + expect(deleteSpanCount, 1); + + _verifySpan( + expectedDeleteStatement, + tx.children.last, + ); + + _verifySpan( + SentrySpanDescriptions.dbTransaction, + tx.children[1], + operation: SentrySpanOperations.dbSqlTransaction, + ); + }); + + test('successful commit adds custom query spans', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await db.transaction(() async { + await db.customStatement(expectedSelectStatement); + }); + + final customSpanCount = tx.children + .where( + (element) => element.context.description == expectedSelectStatement, + ) + .length; + expect(customSpanCount, 1); + + _verifySpan( + expectedSelectStatement, + tx.children.last, + ); + + _verifySpan( + SentrySpanDescriptions.dbTransaction, + tx.children[1], + operation: SentrySpanOperations.dbSqlTransaction, + ); + }); + + test('successful commit adds batch spans', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await db.transaction(() async { + await _insertIntoBatch(db); + }); + + _verifySpan( + SentrySpanDescriptions.dbBatch(statements: [expectedInsertStatement]), + tx.children.last, + operation: SentrySpanOperations.dbSqlBatch, + ); + }); + + test('batch creates transaction span', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await _insertIntoBatch(db); + + _verifySpan( + SentrySpanDescriptions.dbTransaction, + tx.children[1], + operation: SentrySpanOperations.dbSqlTransaction, + ); + + _verifySpan( + SentrySpanDescriptions.dbBatch(statements: [expectedInsertStatement]), + tx.children.last, + operation: SentrySpanOperations.dbSqlBatch, + ); + }); + + test('rollback case adds aborted span', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + await _insertRow(db); + await _insertRow(db); + + try { + await db.transaction(() async { + await _insertRow(db, withError: true); + }); + } catch (_) {} + + final spans = + tx.children.where((child) => child.status == SpanStatus.aborted()); + expect(spans.length, 1); + final abortedSpan = spans.first; + + expect(sut.spanHelper.transactionStack, isEmpty); + _verifySpan( + SentrySpanDescriptions.dbTransaction, + abortedSpan, + status: SpanStatus.aborted(), + operation: SentrySpanOperations.dbSqlTransaction, + ); + }); + + test('batch does not add span for failed operations', () async { + final sut = fixture.getSut(); + final db = AppDatabase(NativeDatabase.memory().interceptWith(sut)); + + final tx = _startTransaction(); + try { + await db.batch((batch) async { + await _insertRow(db, withError: true); + await _insertRow(db); + }); + } catch (_) {} + + expect(tx.children.isEmpty, true); + }); + + test('error case adds error span', () async { + final exception = Exception('test'); + final queryExecutor = MockQueryExecutor(); + when(queryExecutor.ensureOpen(any)).thenAnswer((_) => Future.value(true)); + when(queryExecutor.beginTransaction()).thenThrow(exception); + when(queryExecutor.dialect).thenReturn(SqlDialect.sqlite); + + final sut = fixture.getSut(); + final db = AppDatabase(queryExecutor.interceptWith(sut)); + + final tx = _startTransaction(); + try { + await db.transaction(() async { + await _insertRow(db); + }); + } catch (e) { + // making sure the thrown exception doesn't fail the test + } + + // when beginTransaction errored, we don't add it to the stack + expect(sut.spanHelper.transactionStack, isEmpty); + _verifyErrorSpan( + operation: SentrySpanOperations.dbSqlTransaction, + SentrySpanDescriptions.dbTransaction, + exception, + tx.children.last, + ); + }); + }); + + group('integrations', () { + setUp(() async { + // init the interceptor so the integrations are added + fixture.getSut(); + }); + + test('adds integration', () { + expect( + fixture.options.sdk.integrations + .contains(drift_constants.integrationName), + true, + ); + }); + + test('adds package', () { + expect( + fixture.options.sdk.packages.any( + (element) => + element.name == packageName && element.version == sdkVersion, + ), + true, + ); + }); + }); +} + +class Fixture { + static final dbName = 'test_db_name'; + final options = defaultTestOptions()..tracesSampleRate = 1.0; + + Future sentryInit() { + return Sentry.init( + (options) {}, + options: options, + ); + } + + SentryQueryInterceptor getSut() { + driftRuntimeOptions.dontWarnAboutMultipleDatabases = true; + return SentryQueryInterceptor(databaseName: dbName); + } +} + +void _verifySpan( + String description, + SentrySpan? span, { + String? operation, + SpanStatus? status, +}) { + status ??= SpanStatus.ok(); + expect( + span?.context.operation, + operation ?? SentrySpanOperations.dbSqlQuery, + ); + expect(span?.context.description, description); + expect(span?.status, status); + expect(span?.origin, SentryTraceOrigins.autoDbDriftQueryInterceptor); + expect( + span?.data[SentrySpanData.dbSystemKey], + SentrySpanData.dbSystemSqlite, + ); + expect( + span?.data[SentrySpanData.dbNameKey], + Fixture.dbName, + ); +} + +void _verifyErrorSpan( + String description, + Exception exception, + SentrySpan? span, { + String? operation, + SpanStatus? status, +}) { + expect( + span?.context.operation, + operation ?? SentrySpanOperations.dbSqlQuery, + ); + expect(span?.context.description, description); + expect(span?.status, status ?? SpanStatus.internalError()); + expect(span?.origin, SentryTraceOrigins.autoDbDriftQueryInterceptor); + expect( + span?.data[SentrySpanData.dbSystemKey], + SentrySpanData.dbSystemSqlite, + ); + expect( + span?.data[SentrySpanData.dbNameKey], + Fixture.dbName, + ); + + expect(span?.throwable, exception); +} + +Future _insertRow(AppDatabase db, {bool withError = false}) { + if (withError) { + return db.into(db.todoItems).insert( + TodoItemsCompanion.insert( + title: '', + content: '', + ), + ); + } else { + return db.into(db.todoItems).insert( + TodoItemsCompanion.insert( + title: 'todo: finish drift setup', + content: 'We can now write queries and define our own tables.', + ), + ); + } +} + +Future _insertIntoBatch(AppDatabase sut) { + return sut.batch((batch) { + batch.insertAll(sut.todoItems, [ + TodoItemsCompanion.insert( + title: 'todo: finish drift setup #1', + content: 'We can now write queries and define our own tables.', + ), + TodoItemsCompanion.insert( + title: 'todo: finish drift setup #2', + content: 'We can now write queries and define our own tables.', + ), + ]); + }); +} + +Future _updateRow(AppDatabase sut, {bool withError = false}) { + if (withError) { + return (sut.update(sut.todoItems) + ..where((tbl) => tbl.title.equals('doesnt exist'))) + .write( + TodoItemsCompanion( + title: Value('after update'), + content: Value('We can now write queries and define our own tables.'), + ), + ); + } else { + return (sut.update(sut.todoItems) + ..where((tbl) => tbl.title.equals('todo: finish drift setup'))) + .write( + TodoItemsCompanion( + title: Value('after update'), + content: Value('We can now write queries and define our own tables.'), + ), + ); + } +} + +SentryTracer _startTransaction() { + return Sentry.startTransaction('drift', 'test op', bindToScope: true) + as SentryTracer; +} diff --git a/drift/test/test_database.g.dart b/drift/test/test_database.g.dart index 65430026da..45207ed14f 100644 --- a/drift/test/test_database.g.dart +++ b/drift/test/test_database.g.dart @@ -160,6 +160,15 @@ class TodoItem extends DataClass implements Insertable { content: content ?? this.content, category: category.present ? category.value : this.category, ); + TodoItem copyWithCompanion(TodoItemsCompanion data) { + return TodoItem( + id: data.id.present ? data.id.value : this.id, + title: data.title.present ? data.title.value : this.title, + content: data.content.present ? data.content.value : this.content, + category: data.category.present ? data.category.value : this.category, + ); + } + @override String toString() { return (StringBuffer('TodoItem(') @@ -260,6 +269,7 @@ class TodoItemsCompanion extends UpdateCompanion { abstract class _$AppDatabase extends GeneratedDatabase { _$AppDatabase(QueryExecutor e) : super(e); + $AppDatabaseManager get managers => $AppDatabaseManager(this); late final $TodoItemsTable todoItems = $TodoItemsTable(this); @override Iterable> get allTables => @@ -267,3 +277,155 @@ abstract class _$AppDatabase extends GeneratedDatabase { @override List get allSchemaEntities => [todoItems]; } + +typedef $$TodoItemsTableCreateCompanionBuilder = TodoItemsCompanion Function({ + Value id, + required String title, + required String content, + Value category, +}); +typedef $$TodoItemsTableUpdateCompanionBuilder = TodoItemsCompanion Function({ + Value id, + Value title, + Value content, + Value category, +}); + +class $$TodoItemsTableFilterComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get title => $composableBuilder( + column: $table.title, builder: (column) => ColumnFilters(column)); + + ColumnFilters get content => $composableBuilder( + column: $table.content, builder: (column) => ColumnFilters(column)); + + ColumnFilters get category => $composableBuilder( + column: $table.category, builder: (column) => ColumnFilters(column)); +} + +class $$TodoItemsTableOrderingComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get title => $composableBuilder( + column: $table.title, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get content => $composableBuilder( + column: $table.content, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get category => $composableBuilder( + column: $table.category, builder: (column) => ColumnOrderings(column)); +} + +class $$TodoItemsTableAnnotationComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get title => + $composableBuilder(column: $table.title, builder: (column) => column); + + GeneratedColumn get content => + $composableBuilder(column: $table.content, builder: (column) => column); + + GeneratedColumn get category => + $composableBuilder(column: $table.category, builder: (column) => column); +} + +class $$TodoItemsTableTableManager extends RootTableManager< + _$AppDatabase, + $TodoItemsTable, + TodoItem, + $$TodoItemsTableFilterComposer, + $$TodoItemsTableOrderingComposer, + $$TodoItemsTableAnnotationComposer, + $$TodoItemsTableCreateCompanionBuilder, + $$TodoItemsTableUpdateCompanionBuilder, + (TodoItem, BaseReferences<_$AppDatabase, $TodoItemsTable, TodoItem>), + TodoItem, + PrefetchHooks Function()> { + $$TodoItemsTableTableManager(_$AppDatabase db, $TodoItemsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$TodoItemsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$TodoItemsTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$TodoItemsTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value title = const Value.absent(), + Value content = const Value.absent(), + Value category = const Value.absent(), + }) => + TodoItemsCompanion( + id: id, + title: title, + content: content, + category: category, + ), + createCompanionCallback: ({ + Value id = const Value.absent(), + required String title, + required String content, + Value category = const Value.absent(), + }) => + TodoItemsCompanion.insert( + id: id, + title: title, + content: content, + category: category, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$TodoItemsTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $TodoItemsTable, + TodoItem, + $$TodoItemsTableFilterComposer, + $$TodoItemsTableOrderingComposer, + $$TodoItemsTableAnnotationComposer, + $$TodoItemsTableCreateCompanionBuilder, + $$TodoItemsTableUpdateCompanionBuilder, + (TodoItem, BaseReferences<_$AppDatabase, $TodoItemsTable, TodoItem>), + TodoItem, + PrefetchHooks Function()>; + +class $AppDatabaseManager { + final _$AppDatabase _db; + $AppDatabaseManager(this._db); + $$TodoItemsTableTableManager get todoItems => + $$TodoItemsTableTableManager(_db, _db.todoItems); +} diff --git a/e2e_test/pubspec.yaml b/e2e_test/pubspec.yaml index 0f53c54ca5..d0ec1b711c 100644 --- a/e2e_test/pubspec.yaml +++ b/e2e_test/pubspec.yaml @@ -5,7 +5,7 @@ version: 1.0.0 publish_to: none environment: - sdk: '>=2.17.0 <4.0.0' + sdk: '>=3.5.0 <4.0.0' dependencies: sentry: diff --git a/file/lib/src/sentry_file_extension.dart b/file/lib/src/sentry_file_extension.dart index 3cc764c36e..3436a3ad8f 100644 --- a/file/lib/src/sentry_file_extension.dart +++ b/file/lib/src/sentry_file_extension.dart @@ -1,8 +1,6 @@ // ignore_for_file: invalid_use_of_internal_member -import 'dart:io' - if (dart.library.html) 'dart:html' - if (dart.library.js_interop) 'dart:js_interop'; +import 'dart:io' if (dart.library.js_interop) 'dart:js_interop'; import 'package:meta/meta.dart'; import 'package:sentry/sentry.dart'; @@ -29,13 +27,10 @@ extension SentryFileExtension on File { /// /// All the copy, create, delete, open, rename, read, and write operations are /// supported. - File sentryTrace({ - @internal Hub? hub, - }) { + File sentryTrace({@internal Hub? hub}) { final _hub = hub ?? HubAdapter(); - if (_hub.options.platformChecker.isWeb || - !_hub.options.isTracingEnabled()) { + if (_hub.options.platform.isWeb || !_hub.options.isTracingEnabled()) { return this; } diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index b283fceb28..c9f320c4f7 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.14.0'; +const String sdkVersion = '9.0.0-alpha.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index ba2eb12d0a..8db4d841fa 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,13 +1,13 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 8.14.0 +version: 9.0.0-alpha.1 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues documentation: https://docs.sentry.io/platforms/dart/configuration/integrations/file/ environment: - sdk: '>=2.19.0 <4.0.0' + sdk: '>=3.5.0 <4.0.0' platforms: android: @@ -17,7 +17,7 @@ platforms: windows: dependencies: - sentry: 8.14.0 + sentry: 9.0.0-alpha.1 meta: ^1.3.0 dev_dependencies: diff --git a/file/test/mock_platform_checker.dart b/file/test/mock_platform_checker.dart deleted file mode 100644 index 6dd95a5c06..0000000000 --- a/file/test/mock_platform_checker.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'no_such_method_provider.dart'; -import 'package:sentry/src/platform_checker.dart'; - -class MockPlatformChecker extends PlatformChecker with NoSuchMethodProvider { - MockPlatformChecker(this._isWeb); - - final bool _isWeb; - - @override - bool get isWeb => _isWeb; -} diff --git a/file/test/mock_sentry_client.dart b/file/test/mock_sentry_client.dart index 8fb4091cd7..e7b083aad5 100644 --- a/file/test/mock_sentry_client.dart +++ b/file/test/mock_sentry_client.dart @@ -17,17 +17,20 @@ class MockSentryClient with NoSuchMethodProvider implements SentryClient { SentryTransaction transaction, { Scope? scope, SentryTraceContextHeader? traceContext, + Hint? hint, }) async { captureTransactionCalls - .add(CaptureTransactionCall(transaction, traceContext, scope)); + .add(CaptureTransactionCall(transaction, scope, traceContext, hint)); return transaction.eventId; } } class CaptureTransactionCall { final SentryTransaction transaction; - final SentryTraceContextHeader? traceContext; final Scope? scope; + final SentryTraceContextHeader? traceContext; + final Hint? hint; - CaptureTransactionCall(this.transaction, this.traceContext, this.scope); + CaptureTransactionCall( + this.transaction, this.scope, this.traceContext, this.hint); } diff --git a/file/test/sentry_file_extension_test.dart b/file/test/sentry_file_extension_test.dart index b56ab335be..cad68cb318 100644 --- a/file/test/sentry_file_extension_test.dart +++ b/file/test/sentry_file_extension_test.dart @@ -5,10 +5,10 @@ import 'dart:io'; import 'package:sentry/sentry.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:sentry_file/sentry_file.dart'; import 'package:test/test.dart'; -import 'mock_platform_checker.dart'; import 'mock_sentry_client.dart'; void main() { @@ -55,7 +55,7 @@ class Fixture { bool isWeb = false, }) { options.tracesSampleRate = tracesSampleRate; - options.platformChecker = MockPlatformChecker(isWeb); + options.platform = MockPlatform(isWeb: isWeb); hub = Hub(options); diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 2b87873b56..4beeae0447 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -34,8 +34,8 @@ android { } defaultConfig { - minSdkVersion 19 - targetSdkVersion 33 + minSdkVersion 21 + targetSdkVersion 34 ndk { // Flutter does not currently support building for x86 Android (See Issue 9253). @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.22.1' + api 'io.sentry:sentry-android:8.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework 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 3cd7a4bb1c..6f336c6c7f 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -1,5 +1,6 @@ package io.sentry.flutter +import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.content.res.Configuration @@ -35,7 +36,6 @@ import io.sentry.protocol.DebugImage import io.sentry.protocol.SentryId import io.sentry.protocol.User import io.sentry.transport.CurrentDateProvider -import java.io.File import java.lang.ref.WeakReference import kotlin.math.roundToInt @@ -49,7 +49,6 @@ class SentryFlutterPlugin : private lateinit var channel: MethodChannel private lateinit var context: Context private lateinit var sentryFlutter: SentryFlutter - private lateinit var replay: ReplayIntegration // Note: initial config because we don't yet have the numbers of the actual Flutter widget. // See how SentryFlutterReplayRecorder.start() handles it. New settings will be set by setReplayConfig() method below. @@ -103,7 +102,6 @@ class SentryFlutterPlugin : "displayRefreshRate" -> displayRefreshRate(result) "nativeCrash" -> crash() "setReplayConfig" -> setReplayConfig(call, result) - "addReplayScreenshot" -> addReplayScreenshot(call.argument("path"), call.argument("timestamp"), result) "captureReplay" -> captureReplay(call.argument("isCrash"), result) else -> result.notImplemented() } @@ -164,15 +162,13 @@ class SentryFlutterPlugin : private fun setupReplay(options: SentryAndroidOptions) { // Replace the default ReplayIntegration with a Flutter-specific recorder. options.integrations.removeAll { it is ReplayIntegration } - val cacheDirPath = options.cacheDirPath val replayOptions = options.sessionReplay - val isReplayEnabled = replayOptions.isSessionReplayEnabled || replayOptions.isSessionReplayForErrorsEnabled - if (cacheDirPath != null && isReplayEnabled) { + if (replayOptions.isSessionReplayEnabled || replayOptions.isSessionReplayForErrorsEnabled) { replay = ReplayIntegration( - context, + context.applicationContext, dateProvider = CurrentDateProvider.getInstance(), - recorderProvider = { SentryFlutterReplayRecorder(channel, replay) }, + recorderProvider = { SentryFlutterReplayRecorder(channel, replay!!) }, recorderConfigProvider = { Log.i( "Sentry", @@ -187,8 +183,8 @@ class SentryFlutterPlugin : }, replayCacheProvider = null, ) - replay.breadcrumbConverter = SentryFlutterReplayBreadcrumbConverter() - options.addIntegration(replay) + replay!!.breadcrumbConverter = SentryFlutterReplayBreadcrumbConverter() + options.addIntegration(replay!!) options.setReplayController(replay) } else { options.setReplayController(null) @@ -529,8 +525,13 @@ class SentryFlutterPlugin : } companion object { + @SuppressLint("StaticFieldLeak") + private var replay: ReplayIntegration? = null + private const val NATIVE_CRASH_WAIT_TIME = 500L + @JvmStatic fun privateSentryGetReplayIntegration(): ReplayIntegration? = replay + private fun crash() { val exception = RuntimeException("FlutterSentry Native Integration: Sample RuntimeException") val mainThread = Looper.getMainLooper().thread @@ -564,19 +565,6 @@ class SentryFlutterPlugin : result.success(serializedScope) } - private fun addReplayScreenshot( - path: String?, - timestamp: Long?, - result: Result, - ) { - if (path == null || timestamp == null) { - result.error("5", "Arguments are null", null) - return - } - replay.onScreenshotRecorded(File(path), timestamp) - result.success("") - } - private fun setReplayConfig( call: MethodCall, result: Result, @@ -626,7 +614,7 @@ class SentryFlutterPlugin : replayConfig.bitRate, ), ) - replay.onConfigurationChanged(Configuration()) + replay!!.onConfigurationChanged(Configuration()) result.success("") } @@ -638,7 +626,7 @@ class SentryFlutterPlugin : result.error("5", "Arguments are null", null) return } - replay.captureReplay(isCrash) - result.success(replay.getReplayId().toString()) + replay!!.captureReplay(isCrash) + result.success(replay!!.getReplayId().toString()) } } diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterReplayRecorder.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterReplayRecorder.kt index c49fc23482..fb86ed4440 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterReplayRecorder.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterReplayRecorder.kt @@ -19,17 +19,11 @@ internal class SentryFlutterReplayRecorder( return } - val cacheDirPath = integration.replayCacheDir?.absolutePath - if (cacheDirPath == null) { - Log.w("Sentry", "Replay cache directory is null, can't start replay recorder.") - return - } Handler(Looper.getMainLooper()).post { try { channel.invokeMethod( "ReplayRecorder.start", mapOf( - "directory" to cacheDirPath, "width" to recorderConfig.recordingWidth, "height" to recorderConfig.recordingHeight, "frameRate" to recorderConfig.frameRate, diff --git a/flutter/example/integration_test/integration_test.dart b/flutter/example/integration_test/integration_test.dart index 8259d02cac..03321ea39d 100644 --- a/flutter/example/integration_test/integration_test.dart +++ b/flutter/example/integration_test/integration_test.dart @@ -84,25 +84,9 @@ void main() { expect(sentryId != const SentryId.empty(), true); }); - testWidgets('setup sentry and capture user feedback', (tester) async { - await setupSentryAndApp(tester); - - // ignore: deprecated_member_use_from_same_package - // ignore: deprecated_member_use - final feedback = SentryUserFeedback( - eventId: SentryId.newId(), - name: 'fixture-name', - email: 'fixture@email.com', - comments: 'fixture-comments'); - // ignore: deprecated_member_use - await Sentry.captureUserFeedback(feedback); - }); - testWidgets('setup sentry and capture feedback', (tester) async { await setupSentryAndApp(tester); - // ignore: deprecated_member_use_from_same_package - // ignore: deprecated_member_use final associatedEventId = await Sentry.captureMessage('Associated'); final feedback = SentryFeedback( message: 'message', diff --git a/flutter/example/integration_test/replay_test.dart b/flutter/example/integration_test/replay_test.dart index 00d85ca14f..07d1fe4f3c 100644 --- a/flutter/example/integration_test/replay_test.dart +++ b/flutter/example/integration_test/replay_test.dart @@ -11,7 +11,7 @@ void main() { options.automatedTestMode = true; options.dsn = 'https://abc@def.ingest.sentry.io/1234567'; options.debug = true; - options.experimental.replay.sessionSampleRate = 1.0; + options.replay.sessionSampleRate = 1.0; }); }); diff --git a/flutter/example/integration_test/web_sdk_test.dart b/flutter/example/integration_test/web_sdk_test.dart index b9436aa432..48ecc2044c 100644 --- a/flutter/example/integration_test/web_sdk_test.dart +++ b/flutter/example/integration_test/web_sdk_test.dart @@ -11,7 +11,6 @@ import 'dart:js_interop_unsafe'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:sentry_flutter/src/web/javascript_transport.dart'; import 'package:sentry_flutter_example/main.dart' as app; import 'utils.dart'; @@ -48,11 +47,14 @@ void main() { group('Web SDK Integration', () { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + tearDown(() async { + await Sentry.close(); + }); + group('enabled', () { testWidgets('Sentry JS SDK initialized', (tester) async { await restoreFlutterOnErrorAfter(() async { await SentryFlutter.init((options) { - options.enableSentryJs = true; options.dsn = fakeDsn; }, appRunner: () async { await tester.pumpWidget(const app.MyApp()); @@ -72,25 +74,20 @@ void main() { }); testWidgets('sends the correct envelope', (tester) async { - SentryFlutterOptions? configuredOptions; SentryEvent? dartEvent; await restoreFlutterOnErrorAfter(() async { await SentryFlutter.init((options) { - options.enableSentryJs = true; options.dsn = fakeDsn; options.beforeSend = (event, hint) { dartEvent = event; return event; }; - configuredOptions = options; }, appRunner: () async { await tester.pumpWidget(const app.MyApp()); }); }); - expect(configuredOptions!.transport, isA()); - final client = _getClient()!; final completer = Completer>(); @@ -110,11 +107,10 @@ void main() { expect((header['sdk'] as Map)['name'], 'sentry.dart.flutter'); - final item = (envelope[1] as List).first as List; - final itemPayloadJs = (item[1] as JSArray).toDart; - final itemPayload = json.decode(utf8.decoder.convert(itemPayloadJs - .map((el) => int.parse(el.dartify().toString())) - .toList())) as Map; + final item = (envelope[1] as List).first as List; + final itemPayload = + json.decode(utf8.decoder.convert(item[1] as List)) + as Map; final jsEventJson = (itemPayload).map((key, value) { return MapEntry(key.toString(), value as dynamic); @@ -132,7 +128,6 @@ void main() { await restoreFlutterOnErrorAfter(() async { await SentryFlutter.init((options) { - options.enableSentryJs = true; options.dsn = fakeDsn; options.attachScreenshot = true; @@ -166,8 +161,8 @@ void main() { testWidgets('Sentry JS SDK is not initialized', (tester) async { await restoreFlutterOnErrorAfter(() async { await SentryFlutter.init((options) { - options.enableSentryJs = false; options.dsn = fakeDsn; + options.autoInitializeNativeSdk = false; }, appRunner: () async { await tester.pumpWidget(const app.MyApp()); }); diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 3df93752fd..ed244a60f2 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:dio/dio.dart'; +import 'package:drift/drift.dart' show ApplyInterceptor; import 'package:feedback/feedback.dart' as feedback; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -81,18 +82,12 @@ Future setupSentry( options.debug = kDebugMode; options.spotlight = Spotlight(enabled: true); options.enableTimeToFullDisplayTracing = true; - options.enableSentryJs = true; options.maxRequestBodySize = MaxRequestBodySize.always; - options.maxResponseBodySize = MaxResponseBodySize.always; options.navigatorKey = navigatorKey; - options.experimental.replay.sessionSampleRate = 1.0; - options.experimental.replay.onErrorSampleRate = 1.0; - - // This has a side-effect of creating the default privacy configuration, - // thus enabling Screenshot masking. No need to actually change it. - options.experimental.privacy; + options.replay.sessionSampleRate = 1.0; + options.replay.onErrorSampleRate = 1.0; _isIntegrationTest = isIntegrationTest; if (_isIntegrationTest) { @@ -346,18 +341,13 @@ class MainScaffold extends StatelessWidget { ), TooltipButton( onPressed: () { - // Only usable on Flutter >= 3.3 - // and needs the following additional setup: - // options.addIntegration(OnErrorIntegration()); - (WidgetsBinding.instance.platformDispatcher as dynamic) - .onError - ?.call( - Exception('PlatformDispatcher.onError'), - StackTrace.current, - ); + WidgetsBinding.instance.platformDispatcher.onError?.call( + Exception('PlatformDispatcher.onError'), + StackTrace.current, + ); }, text: - 'This is only usable on Flutter >= 3.3 and requires additional setup: options.addIntegration(OnErrorIntegration());', + 'This requires additional setup: options.addIntegration(OnErrorIntegration());', buttonTitle: 'Capture from PlatformDispatcher.onError', ), TooltipButton( @@ -660,11 +650,8 @@ class MainScaffold extends StatelessWidget { bindToScope: true, ); - // ignore: deprecated_member_use - final executor = SentryQueryExecutor( - () async => inMemoryExecutor(), - databaseName: 'sentry_in_memory_db', - ); + final executor = inMemoryExecutor().interceptWith( + SentryQueryInterceptor(databaseName: 'sentry_in_memory_db')); final db = AppDatabase(executor); @@ -683,17 +670,6 @@ class MainScaffold extends StatelessWidget { } } -extension BuildContextExtension on BuildContext { - bool get isMounted { - try { - return (this as dynamic).mounted; - } on NoSuchMethodError catch (_) { - // ignore, only available in newer Flutter versions - } - return true; - } -} - class AndroidExample extends StatelessWidget { const AndroidExample({super.key}); @@ -747,7 +723,7 @@ void navigateToAutoCloseScreen(BuildContext context) { MaterialPageRoute( settings: const RouteSettings(name: 'AutoCloseScreen'), // ignore: deprecated_member_use - builder: (context) => SentryDisplayWidget(child: const AutoCloseScreen()), + builder: (context) => const AutoCloseScreen(), ), ); } diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index d1790ec616..72293fa9c7 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,12 +1,12 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 8.14.0 +version: 9.0.0-alpha.1 publish_to: 'none' # Remove this line if you wish to publish to pub.dev environment: - sdk: '>=2.17.0 <4.0.0' - flutter: '>=3.0.0' + sdk: '>=3.5.0 <4.0.0' + flutter: '>=3.24.0' dependencies: flutter: diff --git a/flutter/ffi-jni.yaml b/flutter/ffi-jni.yaml new file mode 100644 index 0000000000..1e4969aa2a --- /dev/null +++ b/flutter/ffi-jni.yaml @@ -0,0 +1,18 @@ +android_sdk_config: + add_gradle_deps: true + android_example: 'example/' + +# summarizer: +# backend: asm + +output: + dart: + path: lib/src/native/java/binding.dart + structure: single_file + +log_level: all + +classes: + - io.sentry.android.replay.ReplayIntegration + - io.sentry.flutter.SentryFlutterPlugin + - android.graphics.Bitmap diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index c7a74edfcb..c9b28c297f 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -20,8 +20,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' - # Flutter 3.7 requires 10.14 - s.osx.deployment_target = '10.13' + s.osx.deployment_target = '10.14' # Flutter.framework does not contain a i386 slice. s.ios.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => '$(inherited) i386' } diff --git a/flutter/ios/sentry_flutter/Package.swift b/flutter/ios/sentry_flutter/Package.swift index f1b219c720..8e5cf7421b 100644 --- a/flutter/ios/sentry_flutter/Package.swift +++ b/flutter/ios/sentry_flutter/Package.swift @@ -7,7 +7,7 @@ let package = Package( name: "sentry_flutter", platforms: [ .iOS("12.0"), - .macOS("10.13") + .macOS("10.14") ], products: [ .library(name: "sentry-flutter", targets: ["sentry_flutter", "sentry_flutter_objc"]) diff --git a/flutter/lib/sentry_flutter.dart b/flutter/lib/sentry_flutter.dart index e531fc9fb8..b1571ec875 100644 --- a/flutter/lib/sentry_flutter.dart +++ b/flutter/lib/sentry_flutter.dart @@ -1,27 +1,26 @@ /// A Flutter client for Sentry.io crash reporting. -library sentry_flutter; +library; // ignore: invalid_export_of_internal_element export 'package:sentry/sentry.dart'; +export 'src/binding_wrapper.dart' + show BindingWrapper, SentryWidgetsFlutterBinding; +export 'src/feedback/sentry_feedback_widget.dart'; +export 'src/flutter_sentry_attachment.dart'; export 'src/integrations/load_release_integration.dart'; +export 'src/integrations/on_error_integration.dart'; export 'src/navigation/sentry_navigator_observer.dart'; -export 'src/sentry_flutter.dart'; -export 'src/sentry_flutter_options.dart'; -export 'src/sentry_replay_options.dart'; export 'src/replay/replay_quality.dart'; -export 'src/sentry_privacy_options.dart'; -export 'src/flutter_sentry_attachment.dart'; -export 'src/sentry_asset_bundle.dart' show SentryAssetBundle; -export 'src/integrations/on_error_integration.dart'; export 'src/screenshot/masking_config.dart' show SentryMaskingDecision; export 'src/screenshot/sentry_mask_widget.dart'; -export 'src/screenshot/sentry_unmask_widget.dart'; -export 'src/screenshot/sentry_screenshot_widget.dart'; export 'src/screenshot/sentry_screenshot_quality.dart'; -export 'src/user_interaction/sentry_user_interaction_widget.dart'; -export 'src/binding_wrapper.dart' - show BindingWrapper, SentryWidgetsFlutterBinding; +export 'src/screenshot/sentry_screenshot_widget.dart'; +export 'src/screenshot/sentry_unmask_widget.dart'; +export 'src/sentry_asset_bundle.dart' show SentryAssetBundle; +export 'src/sentry_flutter.dart'; +export 'src/sentry_flutter_options.dart'; +export 'src/sentry_privacy_options.dart'; +export 'src/sentry_replay_options.dart'; export 'src/sentry_widget.dart'; -export 'src/navigation/sentry_display_widget.dart'; -export 'src/feedback/sentry_feedback_widget.dart'; +export 'src/user_interaction/sentry_user_interaction_widget.dart'; diff --git a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart index dae174f657..dbadf223eb 100644 --- a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart +++ b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart @@ -3,6 +3,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:sentry/sentry.dart'; import '../navigation/sentry_navigator_observer.dart'; @@ -18,8 +19,8 @@ class FlutterEnricherEventProcessor implements EventProcessor { final SentryFlutterOptions _options; - bool get _hasNativeIntegration => _checker.hasNativeIntegration; - PlatformChecker get _checker => _options.platformChecker; + bool get _hasNativeIntegration => _options.platform.supportsNativeIntegration; + RuntimeChecker get _checker => _options.runtimeChecker; // We can't use `WidgetsBinding` as a direct parameter // because it must be called inside the `runZoneGuarded`-Integration. @@ -39,7 +40,7 @@ class FlutterEnricherEventProcessor implements EventProcessor { // information available than Flutter. // TODO: while we have a native integration with JS SDK, it's currently opt in and we dont gather contexts yet // so for web it's still better to rely on the information of Flutter. - final device = _hasNativeIntegration && !_checker.isWeb + final device = _hasNativeIntegration && !_options.platform.isWeb ? null : _getDevice(event.contexts.device); @@ -137,8 +138,6 @@ class FlutterEnricherEventProcessor implements EventProcessor { // ignore: deprecated_member_use final hasRenderView = _widgetsBinding?.renderViewElement != null; - final renderer = _options.rendererWrapper.getRenderer()?.name; - return { 'has_render_view': hasRenderView.toString(), if (tempDebugBrightnessOverride != null) @@ -155,8 +154,7 @@ class FlutterEnricherEventProcessor implements EventProcessor { // Also always fails in tests. // See https://github.com/flutter/flutter/issues/83919 // 'window_is_visible': _window.viewConfiguration.visible, - if (renderer != null) 'renderer': renderer, - if (_appFlavor != null) 'appFlavor': _appFlavor!, + if (appFlavor != null) 'appFlavor': appFlavor!, }; } @@ -208,7 +206,7 @@ class FlutterEnricherEventProcessor implements EventProcessor { // See // - https://flutter.dev/docs/testing/build-modes // - https://github.com/flutter/flutter/wiki/Flutter%27s-modes - if (_checker.isWeb) { + if (_options.platform.isWeb) { if (_checker.isDebugMode()) { compiler = 'dartdevc'; } else if (_checker.isReleaseMode() || _checker.isProfileMode()) { @@ -270,10 +268,3 @@ class FlutterEnricherEventProcessor implements EventProcessor { return null; } } - -/// Copied from https://api.flutter.dev/flutter/services/appFlavor-constant.html -/// As soon as Flutter 3.16 is the minimal supported version of Sentry, this -/// can be replaced with the property from the link above. -const String? _appFlavor = String.fromEnvironment('FLUTTER_APP_FLAVOR') != '' - ? String.fromEnvironment('FLUTTER_APP_FLAVOR') - : null; diff --git a/flutter/lib/src/event_processor/screenshot_event_processor.dart b/flutter/lib/src/event_processor/screenshot_event_processor.dart index 23ee438948..17de36b99a 100644 --- a/flutter/lib/src/event_processor/screenshot_event_processor.dart +++ b/flutter/lib/src/event_processor/screenshot_event_processor.dart @@ -1,13 +1,11 @@ import 'dart:async'; import 'dart:typed_data'; -import 'dart:ui'; import 'package:meta/meta.dart'; import '../../sentry_flutter.dart'; import '../renderer/renderer.dart'; import '../screenshot/recorder.dart'; import '../screenshot/recorder_config.dart'; -import 'package:flutter/widgets.dart' as widget; import '../utils/debouncer.dart'; @@ -52,18 +50,13 @@ class ScreenshotEventProcessor implements EventProcessor { // skip capturing in case of debouncing (=too many frequent capture requests) // the BeforeCaptureCallback may overrule the debouncing decision final shouldDebounce = _debouncer.shouldDebounce(); - - // ignore: deprecated_member_use_from_same_package - final beforeScreenshot = _options.beforeScreenshot; - final beforeCapture = _options.beforeCaptureScreenshot; + final beforeCaptureScreenshot = _options.beforeCaptureScreenshot; try { FutureOr? result; - if (beforeCapture != null) { - result = beforeCapture(event, hint, shouldDebounce); - } else if (beforeScreenshot != null) { - result = beforeScreenshot(event, hint: hint); + if (beforeCaptureScreenshot != null) { + result = beforeCaptureScreenshot(event, hint, shouldDebounce); } bool takeScreenshot = true; @@ -99,8 +92,7 @@ class ScreenshotEventProcessor implements EventProcessor { final renderer = _options.rendererWrapper.getRenderer(); - if (_options.platformChecker.isWeb && - renderer != FlutterRenderer.canvasKit) { + if (_options.platform.isWeb && renderer != FlutterRenderer.canvasKit) { _options.logger( SentryLevel.debug, 'Cannot take screenshot with ${renderer?.name} renderer.', @@ -108,14 +100,6 @@ class ScreenshotEventProcessor implements EventProcessor { return event; } - if (_options.attachScreenshotOnlyWhenResumed && - widget.WidgetsBinding.instance.lifecycleState != - AppLifecycleState.resumed) { - _options.logger(SentryLevel.debug, - 'Only attaching screenshots when application state is resumed.'); - return event; - } - final screenshotData = await createScreenshot(); if (screenshotData != null) { hint.screenshot = SentryAttachment.fromScreenshotData(screenshotData); diff --git a/flutter/lib/src/event_processor/url_filter/html_url_filter_event_processor.dart b/flutter/lib/src/event_processor/url_filter/html_url_filter_event_processor.dart deleted file mode 100644 index acd00daeb9..0000000000 --- a/flutter/lib/src/event_processor/url_filter/html_url_filter_event_processor.dart +++ /dev/null @@ -1,39 +0,0 @@ -// ignore: deprecated_member_use -import 'dart:html' as html show window, Window; - -// ignore: implementation_imports -import 'package:sentry/src/utils/regex_utils.dart'; - -import '../../../sentry_flutter.dart'; -import 'url_filter_event_processor.dart'; - -// ignore_for_file: invalid_use_of_internal_member - -UrlFilterEventProcessor urlFilterEventProcessor(SentryFlutterOptions options) => - WebUrlFilterEventProcessor(options); - -class WebUrlFilterEventProcessor implements UrlFilterEventProcessor { - WebUrlFilterEventProcessor( - this._options, - ); - - final html.Window _window = html.window; - final SentryFlutterOptions _options; - - @override - SentryEvent? apply(SentryEvent event, Hint hint) { - final url = _window.location.toString(); - - if (_options.allowUrls.isNotEmpty && - !isMatchingRegexPattern(url, _options.allowUrls)) { - return null; - } - - if (_options.denyUrls.isNotEmpty && - isMatchingRegexPattern(url, _options.denyUrls)) { - return null; - } - - return event; - } -} diff --git a/flutter/lib/src/event_processor/url_filter/url_filter_event_processor.dart b/flutter/lib/src/event_processor/url_filter/url_filter_event_processor.dart index 5a1e5ed537..170507d5e9 100644 --- a/flutter/lib/src/event_processor/url_filter/url_filter_event_processor.dart +++ b/flutter/lib/src/event_processor/url_filter/url_filter_event_processor.dart @@ -1,6 +1,5 @@ import '../../../sentry_flutter.dart'; import 'io_url_filter_event_processor.dart' - if (dart.library.html) 'html_url_filter_event_processor.dart' if (dart.library.js_interop) 'web_url_filter_event_processor.dart'; abstract class UrlFilterEventProcessor implements EventProcessor { diff --git a/flutter/lib/src/event_processor/url_filter/web_url_filter_event_processor.dart b/flutter/lib/src/event_processor/url_filter/web_url_filter_event_processor.dart index 3b94afeed8..af35a04a7d 100644 --- a/flutter/lib/src/event_processor/url_filter/web_url_filter_event_processor.dart +++ b/flutter/lib/src/event_processor/url_filter/web_url_filter_event_processor.dart @@ -1,11 +1,9 @@ -// We would lose compatibility with old dart versions by adding web to pubspec. -// ignore: depend_on_referenced_packages +// ignore: implementation_imports +import 'package:sentry/src/utils/regex_utils.dart'; import 'package:web/web.dart' as web show window, Window; import '../../../sentry_flutter.dart'; import 'url_filter_event_processor.dart'; -// ignore: implementation_imports -import 'package:sentry/src/utils/regex_utils.dart'; // ignore_for_file: invalid_use_of_internal_member diff --git a/flutter/lib/src/feedback/sentry_feedback_widget.dart b/flutter/lib/src/feedback/sentry_feedback_widget.dart index 297c9318ce..12f3df4383 100644 --- a/flutter/lib/src/feedback/sentry_feedback_widget.dart +++ b/flutter/lib/src/feedback/sentry_feedback_widget.dart @@ -206,13 +206,6 @@ class _SentryFeedbackWidgetState extends State { hint = Hint.withScreenshot(screenshot); } await _captureFeedback(feedback, hint); - - bool mounted; - try { - mounted = (this as dynamic).mounted as bool; - } on NoSuchMethodError catch (_) { - mounted = false; - } if (mounted) { // ignore: use_build_context_synchronously await Navigator.maybePop(context); diff --git a/flutter/lib/src/integrations/connectivity/connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/connectivity_provider.dart index ea27f80f72..3ee2690627 100644 --- a/flutter/lib/src/integrations/connectivity/connectivity_provider.dart +++ b/flutter/lib/src/integrations/connectivity/connectivity_provider.dart @@ -1,5 +1,4 @@ import 'noop_connectivity_provider.dart' - if (dart.library.html) 'html_connectivity_provider.dart' if (dart.library.js_interop) 'web_connectivity_provider.dart'; abstract class ConnectivityProvider { diff --git a/flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart deleted file mode 100644 index 1b30376aaf..0000000000 --- a/flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'dart:async'; -// ignore: deprecated_member_use -import 'dart:html' as html; - -import 'connectivity_provider.dart'; - -ConnectivityProvider connectivityProvider() { - return WebConnectivityProvider(); -} - -class WebConnectivityProvider implements ConnectivityProvider { - StreamSubscription? _onOnlineSub; - StreamSubscription? _onOfflineSub; - - @override - void listen(void Function(String connectivity) onChange) { - _onOnlineSub = html.window.onOnline.listen((_) { - onChange('wifi'); - }); - _onOfflineSub = html.window.onOffline.listen((_) { - onChange('none'); - }); - } - - @override - void cancel() { - _onOnlineSub?.cancel(); - _onOnlineSub = null; - - _onOfflineSub?.cancel(); - _onOfflineSub = null; - } -} diff --git a/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart index d1c18af777..19d2bc6da6 100644 --- a/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart +++ b/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart @@ -1,7 +1,5 @@ import 'dart:async'; -// We would lose compatibility with old dart versions by adding web to pubspec. -// ignore: depend_on_referenced_packages import 'package:web/web.dart' as web; import 'connectivity_provider.dart'; diff --git a/flutter/lib/src/integrations/debug_print_integration.dart b/flutter/lib/src/integrations/debug_print_integration.dart index fbeb1cb6c1..faeb97eaad 100644 --- a/flutter/lib/src/integrations/debug_print_integration.dart +++ b/flutter/lib/src/integrations/debug_print_integration.dart @@ -18,7 +18,7 @@ class DebugPrintIntegration implements Integration { _hub = hub; _options = options; - final isDebug = options.platformChecker.isDebugMode(); + final isDebug = options.runtimeChecker.isDebugMode(); final enablePrintBreadcrumbs = options.enablePrintBreadcrumbs; if (isDebug || !enablePrintBreadcrumbs) { return; diff --git a/flutter/lib/src/integrations/load_image_list_integration.dart b/flutter/lib/src/integrations/load_image_list_integration.dart index 3643dcb83d..f10883d203 100644 --- a/flutter/lib/src/integrations/load_image_list_integration.dart +++ b/flutter/lib/src/integrations/load_image_list_integration.dart @@ -44,7 +44,7 @@ class _LoadImageListIntegrationEventProcessor implements EventProcessor { // On windows, we need to add the ELF debug image of the AOT code. // See https://github.com/flutter/flutter/issues/154840 - if (_options.platformChecker.platform.isWindows) { + if (_options.platform.isWindows) { final debugImage = _dartProcessor.getAppDebugImage(stackTrace); if (debugImage != null) { images ??= List.empty(); diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index a57adead46..b2b55d2bfa 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -1,8 +1,5 @@ -import 'dart:async'; import 'dart:ui'; -import 'package:meta/meta.dart'; - import '../../sentry_flutter.dart'; import '../frame_callback_handler.dart'; import 'native_app_start_handler.dart'; @@ -15,21 +12,7 @@ class NativeAppStartIntegration extends Integration { final FrameCallbackHandler _frameCallbackHandler; final NativeAppStartHandler _nativeAppStartHandler; - DateTime? _appStartEnd; - - /// This timestamp marks the end of app startup. Either set by calling - // ignore: deprecated_member_use_from_same_package - /// [SentryFlutter.setAppStartEnd]. The [SentryFlutterOptions.autoAppStart] - /// option needs to be false. - @internal - set appStartEnd(DateTime appStartEnd) { - _appStartEnd = appStartEnd; - if (!_appStartEndCompleter.isCompleted) { - _appStartEndCompleter.complete(); - } - } - final Completer _appStartEndCompleter = Completer(); bool _allowProcessing = true; @override @@ -43,27 +26,14 @@ class NativeAppStartIntegration extends Integration { _allowProcessing = false; try { - DateTime? appStartEnd; - // ignore: deprecated_member_use_from_same_package - if (options.autoAppStart) { - // ignore: invalid_use_of_internal_member - appStartEnd = DateTime.fromMicrosecondsSinceEpoch(timings.first - .timestampInMicroseconds(FramePhase.rasterFinishWallTime)); - } else if (_appStartEnd == null) { - await _appStartEndCompleter.future.timeout( - const Duration(seconds: 10), - ); - appStartEnd = _appStartEnd; - } else { - appStartEnd = null; - } - if (appStartEnd != null) { - await _nativeAppStartHandler.call( - hub, - options, - appStartEnd: appStartEnd, - ); - } + // ignore: invalid_use_of_internal_member + final appStartEnd = DateTime.fromMicrosecondsSinceEpoch(timings.first + .timestampInMicroseconds(FramePhase.rasterFinishWallTime)); + await _nativeAppStartHandler.call( + hub, + options, + appStartEnd: appStartEnd, + ); } catch (exception, stackTrace) { options.logger( SentryLevel.error, diff --git a/flutter/lib/src/integrations/on_error_integration.dart b/flutter/lib/src/integrations/on_error_integration.dart index 67c3b1100b..320981986c 100644 --- a/flutter/lib/src/integrations/on_error_integration.dart +++ b/flutter/lib/src/integrations/on_error_integration.dart @@ -1,6 +1,7 @@ import 'package:sentry/sentry.dart'; // ignore: implementation_imports import 'package:sentry/src/utils/stacktrace_utils.dart'; + import '../sentry_flutter_options.dart'; import '../utils/platform_dispatcher_wrapper.dart'; @@ -11,7 +12,6 @@ typedef ErrorCallback = bool Function(Object exception, StackTrace stackTrace); /// - https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/onError.html /// /// Remarks: -/// - Only usable on Flutter >= 3.3.0. /// - Does not work on Flutter Web /// /// This is used instead of [RunZonedGuardedIntegration]. Not using the @@ -94,11 +94,6 @@ class OnErrorIntegration implements Integration { @override void close() { - if (!(dispatchWrapper?.isOnErrorSupported(_options!) == true)) { - // bail out - return; - } - /// Restore default if the integration error is still set. if (dispatchWrapper?.onError == _integrationOnError) { dispatchWrapper?.onError = _defaultOnError; diff --git a/flutter/lib/src/integrations/sdk_integration.dart b/flutter/lib/src/integrations/sdk_integration.dart index c0ca43dc0d..6ed156ad94 100644 --- a/flutter/lib/src/integrations/sdk_integration.dart +++ b/flutter/lib/src/integrations/sdk_integration.dart @@ -1,3 +1,2 @@ export 'native_sdk_integration.dart' - if (dart.library.html) 'web_sdk_integration.dart' if (dart.library.js_interop) 'web_sdk_integration.dart'; diff --git a/flutter/lib/src/integrations/web_sdk_integration.dart b/flutter/lib/src/integrations/web_sdk_integration.dart index 80bdb0ebd4..98ca504a49 100644 --- a/flutter/lib/src/integrations/web_sdk_integration.dart +++ b/flutter/lib/src/integrations/web_sdk_integration.dart @@ -5,7 +5,6 @@ import 'package:sentry/sentry.dart'; import '../native/sentry_native_binding.dart'; import '../sentry_flutter_options.dart'; -import '../web/javascript_transport.dart'; import '../web/script_loader/sentry_script_loader.dart'; import '../web/sentry_js_bundle.dart'; @@ -27,21 +26,18 @@ class WebSdkIntegration implements Integration { @override FutureOr call(Hub hub, SentryFlutterOptions options) async { - if (!options.enableSentryJs || !options.autoInitializeNativeSdk) { + if (!options.autoInitializeNativeSdk) { return; } _options = options; try { - final scripts = options.platformChecker.isDebugMode() + final scripts = options.runtimeChecker.isDebugMode() ? debugScripts : productionScripts; await _scriptLoader.loadWebSdk(scripts); await _web.init(hub); - if (_web.supportsCaptureEnvelope) { - options.transport = JavascriptTransport(_web, options); - } options.sdk.addIntegration(name); } catch (exception, stackTrace) { options.logger( diff --git a/flutter/lib/src/native/c/binding.dart b/flutter/lib/src/native/c/binding.dart index 5d944edf0b..3c32ec9adf 100644 --- a/flutter/lib/src/native/c/binding.dart +++ b/flutter/lib/src/native/c/binding.dart @@ -869,7 +869,7 @@ class SentryNative { /// frozen but lists and dicts are not and can be frozen on demand. This /// automatically happens for some shared values in the event payload like /// the module list. -class sentry_value_u extends ffi.Union { +final class sentry_value_u extends ffi.Union { @ffi.Uint64() external int _bits; @@ -891,4 +891,4 @@ abstract class sentry_value_type_t { /// The Sentry Client Options. /// /// See https://docs.sentry.io/platforms/native/configuration/ -class sentry_options_s extends ffi.Opaque {} +final class sentry_options_s extends ffi.Opaque {} diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index 97112eacac..e05cec9a13 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -31347,13 +31347,13 @@ class NSObject extends _ObjCWrapper { } } -class ObjCSel extends ffi.Opaque {} +final class ObjCSel extends ffi.Opaque {} -class ObjCObject extends ffi.Opaque {} +final class ObjCObject extends ffi.Opaque {} typedef instancetype = ffi.Pointer; -class _NSZone extends ffi.Opaque {} +final class _NSZone extends ffi.Opaque {} class Protocol extends _ObjCWrapper { Protocol._(ffi.Pointer id, SentryCocoa lib, @@ -34515,7 +34515,7 @@ class NSData extends NSObject { } } -class _NSRange extends ffi.Struct { +final class _NSRange extends ffi.Struct { @ffi.UnsignedLong() external int location; @@ -35969,7 +35969,7 @@ class NSValue extends NSObject { } } -class CGPoint extends ffi.Struct { +final class CGPoint extends ffi.Struct { @ffi.Double() external double x; @@ -35977,7 +35977,7 @@ class CGPoint extends ffi.Struct { external double y; } -class CGSize extends ffi.Struct { +final class CGSize extends ffi.Struct { @ffi.Double() external double width; @@ -35985,13 +35985,13 @@ class CGSize extends ffi.Struct { external double height; } -class CGRect extends ffi.Struct { +final class CGRect extends ffi.Struct { external CGPoint origin; external CGSize size; } -class NSEdgeInsets extends ffi.Struct { +final class NSEdgeInsets extends ffi.Struct { @ffi.Double() external double top; @@ -37012,7 +37012,7 @@ class ObjCBlock_ObjCObject_NSError_NSString extends _ObjCBlockBase { } } -class _ObjCBlockDesc extends ffi.Struct { +final class _ObjCBlockDesc extends ffi.Struct { @ffi.UnsignedLong() external int reserved; @@ -37026,7 +37026,7 @@ class _ObjCBlockDesc extends ffi.Struct { external ffi.Pointer signature; } -class _ObjCBlock extends ffi.Struct { +final class _ObjCBlock extends ffi.Struct { external ffi.Pointer isa; @ffi.Int() @@ -38226,7 +38226,7 @@ class NSPredicate extends NSObject { } } -class __va_list_tag extends ffi.Struct { +final class __va_list_tag extends ffi.Struct { @ffi.UnsignedInt() external int gp_offset; @@ -39068,7 +39068,7 @@ class ObjCBlock_bool_ObjCObject_ObjCObject_bool extends _ObjCBlockBase { } } -class NSFastEnumerationState extends ffi.Struct { +final class NSFastEnumerationState extends ffi.Struct { @ffi.UnsignedLong() external int state; @@ -47029,7 +47029,7 @@ class NSRunLoop extends NSObject { } } -class __CFRunLoop extends ffi.Opaque {} +final class __CFRunLoop extends ffi.Opaque {} class NSTimer extends NSObject { NSTimer._(ffi.Pointer id, SentryCocoa lib, @@ -49003,14 +49003,14 @@ class NSAppleEventDescriptor extends NSObject { } @ffi.Packed(2) -class AEDesc extends ffi.Struct { +final class AEDesc extends ffi.Struct { @ffi.UnsignedInt() external int descriptorType; external ffi.Pointer> dataHandle; } -class OpaqueAEDataStorageType extends ffi.Opaque {} +final class OpaqueAEDataStorageType extends ffi.Opaque {} abstract class NSAppleEventSendOptions { static const int NSAppleEventSendNoReply = 1; @@ -57166,7 +57166,7 @@ class NSScanner extends NSObject { } } -class NSDecimal extends ffi.Opaque {} +final class NSDecimal extends ffi.Opaque {} class NSException extends NSObject { NSException._(ffi.Pointer id, SentryCocoa lib, @@ -61912,7 +61912,7 @@ class NSProcessInfo extends NSObject { } } -class NSOperatingSystemVersion extends ffi.Struct { +final class NSOperatingSystemVersion extends ffi.Struct { @ffi.Long() external int majorVersion; @@ -63937,9 +63937,9 @@ abstract class NSURLCredentialPersistence { static const int NSURLCredentialPersistenceSynchronizable = 3; } -class __SecIdentity extends ffi.Opaque {} +final class __SecIdentity extends ffi.Opaque {} -class __SecTrust extends ffi.Opaque {} +final class __SecTrust extends ffi.Opaque {} class NSURLProtectionSpace extends NSObject { NSURLProtectionSpace._(ffi.Pointer id, SentryCocoa lib, diff --git a/flutter/lib/src/native/cocoa/cocoa_replay_recorder.dart b/flutter/lib/src/native/cocoa/cocoa_replay_recorder.dart index 6393b2656e..531baf3b65 100644 --- a/flutter/lib/src/native/cocoa/cocoa_replay_recorder.dart +++ b/flutter/lib/src/native/cocoa/cocoa_replay_recorder.dart @@ -16,8 +16,7 @@ class CocoaReplayRecorder { CocoaReplayRecorder(this._options) : _recorder = ReplayScreenshotRecorder( ScreenshotRecorderConfig( - pixelRatio: - _options.experimental.replay.quality.resolutionScalingFactor, + pixelRatio: _options.replay.quality.resolutionScalingFactor, ), _options, ); diff --git a/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart b/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart index 56f7a4ef13..a43a218156 100644 --- a/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart +++ b/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart @@ -18,13 +18,13 @@ class SentryNativeCocoa extends SentryNativeChannel { SentryNativeCocoa(super.options); @override - bool get supportsReplay => options.platformChecker.platform.isIOS; + bool get supportsReplay => options.platform.isIOS; @override Future init(Hub hub) async { // We only need these when replay is enabled (session or error capture) // so let's set it up conditionally. This allows Dart to trim the code. - if (options.experimental.replay.isEnabled) { + if (options.replay.isEnabled) { channel.setMethodCallHandler((call) async { switch (call.method) { case 'captureReplayScreenshot': diff --git a/flutter/lib/src/native/factory.dart b/flutter/lib/src/native/factory.dart index c81c526594..e45ab999f7 100644 --- a/flutter/lib/src/native/factory.dart +++ b/flutter/lib/src/native/factory.dart @@ -1,3 +1 @@ -export 'factory_real.dart' - if (dart.library.html) 'factory_web.dart' - if (dart.library.js_interop) 'factory_web.dart'; +export 'factory_real.dart' if (dart.library.js_interop) 'factory_web.dart'; diff --git a/flutter/lib/src/native/factory_real.dart b/flutter/lib/src/native/factory_real.dart index 8824d781bf..57a78bbd75 100644 --- a/flutter/lib/src/native/factory_real.dart +++ b/flutter/lib/src/native/factory_real.dart @@ -6,7 +6,7 @@ import 'sentry_native_binding.dart'; import 'sentry_native_channel.dart'; SentryNativeBinding createBinding(SentryFlutterOptions options) { - final platform = options.platformChecker.platform; + final platform = options.platform; if (platform.isIOS || platform.isMacOS) { return SentryNativeCocoa(options); } else if (platform.isAndroid) { diff --git a/flutter/lib/src/native/java/android_replay_recorder.dart b/flutter/lib/src/native/java/android_replay_recorder.dart index 2719558fef..f0af91d004 100644 --- a/flutter/lib/src/native/java/android_replay_recorder.dart +++ b/flutter/lib/src/native/java/android_replay_recorder.dart @@ -1,40 +1,63 @@ +import 'dart:async'; +import 'dart:isolate'; +import 'dart:typed_data'; + +import 'package:jni/jni.dart'; import 'package:meta/meta.dart'; import '../../../sentry_flutter.dart'; import '../../replay/scheduled_recorder.dart'; +import '../../replay/scheduled_recorder_config.dart'; import '../../screenshot/screenshot.dart'; -import '../sentry_safe_method_channel.dart'; +import 'binding.dart' as native; +// Note, this is currently not unit-tested because mocking JNI calls is +// cumbersome, see https://github.com/dart-lang/native/issues/1794 @internal class AndroidReplayRecorder extends ScheduledScreenshotRecorder { - final SentrySafeMethodChannel _channel; - final String _cacheDir; + _AndroidNativeReplayWorker? _worker; + + @internal // visible for testing, used by SentryNativeJava + static AndroidReplayRecorder Function( + ScheduledScreenshotRecorderConfig, SentryFlutterOptions) factory = + AndroidReplayRecorder.new; - AndroidReplayRecorder( - super.config, super.options, this._channel, this._cacheDir) { + AndroidReplayRecorder(super.config, super.options) { super.callback = _addReplayScreenshot; } + @override + Future start() async { + final spawningWorker = _AndroidNativeReplayWorker.spawn(); + super.start(); + _worker = await spawningWorker; + } + + @override + Future stop() async { + await super.stop(); + _worker?.close(); + _worker = null; + } + Future _addReplayScreenshot( Screenshot screenshot, bool isNewlyCaptured) async { final timestamp = screenshot.timestamp.millisecondsSinceEpoch; - final filePath = "$_cacheDir/$timestamp.png"; try { - final pngData = await screenshot.pngData; + final data = await screenshot.rawRgbaData; options.logger( SentryLevel.debug, - '$logName: saving ${isNewlyCaptured ? 'new' : 'repeated'} screenshot to' - ' $filePath (${screenshot.width}x${screenshot.height} pixels, ' - '${pngData.lengthInBytes} bytes)'); - await options.fileSystem - .file(filePath) - .writeAsBytes(pngData.buffer.asUint8List(), flush: true); - - await _channel.invokeMethod( - 'addReplayScreenshot', - {'path': filePath, 'timestamp': timestamp}, - ); + '$logName: captured screenshot (' + '${screenshot.width}x${screenshot.height} pixels, ' + '${data.lengthInBytes} bytes)'); + + await _worker!.nativeAddScreenshot(_WorkItem( + timestamp: timestamp, + data: data.buffer.asUint8List(), + width: screenshot.width, + height: screenshot.height, + )); } catch (error, stackTrace) { options.logger( SentryLevel.error, @@ -48,3 +71,140 @@ class AndroidReplayRecorder extends ScheduledScreenshotRecorder { } } } + +// Based on https://dart.dev/language/isolates#robust-ports-example +class _AndroidNativeReplayWorker { + final SendPort _commands; + final ReceivePort _responses; + final Map> _activeRequests = {}; + int _idCounter = 0; + bool _closed = false; + + static Future<_AndroidNativeReplayWorker> spawn() async { + // Create a receive port and add its initial message handler + final initPort = RawReceivePort(); + final connection = Completer<(ReceivePort, SendPort)>.sync(); + initPort.handler = (SendPort commandPort) { + connection.complete(( + ReceivePort.fromRawReceivePort(initPort), + commandPort, + )); + }; + + // Spawn the isolate. + try { + await Isolate.spawn(_startRemoteIsolate, (initPort.sendPort), + debugName: 'SentryReplayRecorder'); + } on Object { + initPort.close(); + rethrow; + } + + final (ReceivePort receivePort, SendPort sendPort) = + await connection.future; + + return _AndroidNativeReplayWorker._(receivePort, sendPort); + } + + _AndroidNativeReplayWorker._(this._responses, this._commands) { + _responses.listen(_handleResponsesFromIsolate); + } + + Future nativeAddScreenshot(_WorkItem item) async { + if (_closed) throw StateError('Closed'); + final completer = Completer.sync(); + final id = _idCounter++; + _activeRequests[id] = completer; + _commands.send((id, item)); + return await completer.future; + } + + void _handleResponsesFromIsolate(dynamic message) { + final (int id, Object? response) = message as (int, Object?); + final completer = _activeRequests.remove(id)!; + + if (response is RemoteError) { + completer.completeError(response); + } else { + completer.complete(response); + } + + if (_closed && _activeRequests.isEmpty) _responses.close(); + } + + /// This is the actual Android native implementation, the rest is just plumbing. + static void _handleCommandsToIsolate( + ReceivePort receivePort, + SendPort sendPort, + ) { + // Android Bitmap creation is a bit costly so we reuse it between captures. + native.Bitmap? bitmap; + + final _nativeReplay = native.SentryFlutterPlugin$Companion(null) + .privateSentryGetReplayIntegration()!; + + receivePort.listen((message) { + if (message == 'shutdown') { + receivePort.close(); + return; + } + final (id, item) = message as (int, _WorkItem); + try { + if (bitmap != null) { + if (bitmap!.getWidth() != item.width || + bitmap!.getHeight() != item.height) { + bitmap!.release(); + bitmap = null; + } + } + + // https://developer.android.com/reference/android/graphics/Bitmap#createBitmap(int,%20int,%20android.graphics.Bitmap.Config) + // Note: while the generated API is nullable, the docs say the returned value cannot be null.. + bitmap ??= native.Bitmap.createBitmap$3( + item.width, item.height, native.Bitmap$Config.ARGB_8888); + + final jBuffer = JByteBuffer.fromList(item.data); + try { + bitmap!.copyPixelsFromBuffer(jBuffer); + } finally { + jBuffer.release(); + } + + // TODO timestamp is currently missing in onScreenshotRecorded() + _nativeReplay.onScreenshotRecorded(bitmap!); + + sendPort.send((id, null)); + } catch (e, stacktrace) { + sendPort.send((id, RemoteError(e.toString(), stacktrace.toString()))); + } + }); + } + + static void _startRemoteIsolate(SendPort sendPort) { + final receivePort = ReceivePort(); + sendPort.send(receivePort.sendPort); + _handleCommandsToIsolate(receivePort, sendPort); + } + + void close() { + if (!_closed) { + _closed = true; + _commands.send('shutdown'); + if (_activeRequests.isEmpty) _responses.close(); + } + } +} + +class _WorkItem { + final int timestamp; + final Uint8List data; + final int width; + final int height; + + const _WorkItem({ + required this.timestamp, + required this.data, + required this.width, + required this.height, + }); +} diff --git a/flutter/lib/src/native/java/binding.dart b/flutter/lib/src/native/java/binding.dart new file mode 100644 index 0000000000..6e61ab5d11 --- /dev/null +++ b/flutter/lib/src/native/java/binding.dart @@ -0,0 +1,4084 @@ +// Autogenerated by jnigen. DO NOT EDIT! + +// ignore_for_file: annotate_overrides +// ignore_for_file: argument_type_not_assignable +// ignore_for_file: camel_case_extensions +// ignore_for_file: camel_case_types +// ignore_for_file: constant_identifier_names +// ignore_for_file: doc_directive_unknown +// ignore_for_file: file_names +// ignore_for_file: inference_failure_on_untyped_parameter +// ignore_for_file: invalid_internal_annotation +// ignore_for_file: invalid_use_of_internal_member +// ignore_for_file: library_prefixes +// ignore_for_file: lines_longer_than_80_chars +// ignore_for_file: no_leading_underscores_for_library_prefixes +// ignore_for_file: no_leading_underscores_for_local_identifiers +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: only_throw_errors +// ignore_for_file: overridden_fields +// ignore_for_file: prefer_double_quotes +// ignore_for_file: unintended_html_in_doc_comment +// ignore_for_file: unnecessary_cast +// ignore_for_file: unnecessary_non_null_assertion +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: unused_element +// ignore_for_file: unused_field +// ignore_for_file: unused_import +// ignore_for_file: unused_local_variable +// ignore_for_file: unused_shown_name +// ignore_for_file: use_super_parameters + +import 'dart:core' show Object, String, bool, double, int; +import 'dart:core' as core$_; + +import 'package:jni/_internal.dart' as jni$_; +import 'package:jni/jni.dart' as jni$_; + +/// from: `io.sentry.android.replay.ReplayIntegration` +class ReplayIntegration extends jni$_.JObject { + @jni$_.internal + @core$_.override + final jni$_.JObjType $type; + + @jni$_.internal + ReplayIntegration.fromReference( + jni$_.JReference reference, + ) : $type = type, + super.fromReference(reference); + + static final _class = + jni$_.JClass.forName(r'io/sentry/android/replay/ReplayIntegration'); + + /// The type which includes information such as the signature of this class. + static const nullableType = $ReplayIntegration$NullableType(); + static const type = $ReplayIntegration$Type(); + static final _id_new$ = _class.constructorId( + r'(Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V', + ); + + static final _new$ = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer + )>)>>('globalEnv_NewObject') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer)>(); + + /// from: `public void (android.content.Context context, io.sentry.transport.ICurrentDateProvider iCurrentDateProvider, kotlin.jvm.functions.Function0 function0, kotlin.jvm.functions.Function1 function1, kotlin.jvm.functions.Function1 function11)` + /// The returned object must be released after use, by calling the [release] method. + factory ReplayIntegration( + jni$_.JObject context, + jni$_.JObject iCurrentDateProvider, + jni$_.JObject? function0, + jni$_.JObject? function1, + jni$_.JObject? function11, + ) { + final _$context = context.reference; + final _$iCurrentDateProvider = iCurrentDateProvider.reference; + final _$function0 = function0?.reference ?? jni$_.jNullReference; + final _$function1 = function1?.reference ?? jni$_.jNullReference; + final _$function11 = function11?.reference ?? jni$_.jNullReference; + return ReplayIntegration.fromReference(_new$( + _class.reference.pointer, + _id_new$ as jni$_.JMethodIDPtr, + _$context.pointer, + _$iCurrentDateProvider.pointer, + _$function0.pointer, + _$function1.pointer, + _$function11.pointer) + .reference); + } + + static final _id_new$1 = _class.constructorId( + r'(Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V', + ); + + static final _new$1 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_NewObject') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + int, + jni$_.Pointer)>(); + + /// from: `synthetic public void (android.content.Context context, io.sentry.transport.ICurrentDateProvider iCurrentDateProvider, kotlin.jvm.functions.Function0 function0, kotlin.jvm.functions.Function1 function1, kotlin.jvm.functions.Function1 function11, int i, kotlin.jvm.internal.DefaultConstructorMarker defaultConstructorMarker)` + /// The returned object must be released after use, by calling the [release] method. + factory ReplayIntegration.new$1( + jni$_.JObject? context, + jni$_.JObject? iCurrentDateProvider, + jni$_.JObject? function0, + jni$_.JObject? function1, + jni$_.JObject? function11, + int i, + jni$_.JObject? defaultConstructorMarker, + ) { + final _$context = context?.reference ?? jni$_.jNullReference; + final _$iCurrentDateProvider = + iCurrentDateProvider?.reference ?? jni$_.jNullReference; + final _$function0 = function0?.reference ?? jni$_.jNullReference; + final _$function1 = function1?.reference ?? jni$_.jNullReference; + final _$function11 = function11?.reference ?? jni$_.jNullReference; + final _$defaultConstructorMarker = + defaultConstructorMarker?.reference ?? jni$_.jNullReference; + return ReplayIntegration.fromReference(_new$1( + _class.reference.pointer, + _id_new$1 as jni$_.JMethodIDPtr, + _$context.pointer, + _$iCurrentDateProvider.pointer, + _$function0.pointer, + _$function1.pointer, + _$function11.pointer, + i, + _$defaultConstructorMarker.pointer) + .reference); + } + + static final _id_new$2 = _class.constructorId( + r'(Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;)V', + ); + + static final _new$2 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer + )>)>>('globalEnv_NewObject') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer)>(); + + /// from: `public void (android.content.Context context, io.sentry.transport.ICurrentDateProvider iCurrentDateProvider)` + /// The returned object must be released after use, by calling the [release] method. + factory ReplayIntegration.new$2( + jni$_.JObject context, + jni$_.JObject iCurrentDateProvider, + ) { + final _$context = context.reference; + final _$iCurrentDateProvider = iCurrentDateProvider.reference; + return ReplayIntegration.fromReference(_new$2( + _class.reference.pointer, + _id_new$2 as jni$_.JMethodIDPtr, + _$context.pointer, + _$iCurrentDateProvider.pointer) + .reference); + } + + static final _id_new$3 = _class.constructorId( + r'(Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lio/sentry/android/replay/util/MainLooperHandler;Lkotlin/jvm/functions/Function0;)V', + ); + + static final _new$3 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer + )>)>>('globalEnv_NewObject') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer)>(); + + /// from: `public void (android.content.Context context, io.sentry.transport.ICurrentDateProvider iCurrentDateProvider, kotlin.jvm.functions.Function0 function0, kotlin.jvm.functions.Function1 function1, kotlin.jvm.functions.Function1 function11, kotlin.jvm.functions.Function1 function12, io.sentry.android.replay.util.MainLooperHandler mainLooperHandler, kotlin.jvm.functions.Function0 function01)` + /// The returned object must be released after use, by calling the [release] method. + factory ReplayIntegration.new$3( + jni$_.JObject context, + jni$_.JObject iCurrentDateProvider, + jni$_.JObject? function0, + jni$_.JObject? function1, + jni$_.JObject? function11, + jni$_.JObject? function12, + jni$_.JObject? mainLooperHandler, + jni$_.JObject? function01, + ) { + final _$context = context.reference; + final _$iCurrentDateProvider = iCurrentDateProvider.reference; + final _$function0 = function0?.reference ?? jni$_.jNullReference; + final _$function1 = function1?.reference ?? jni$_.jNullReference; + final _$function11 = function11?.reference ?? jni$_.jNullReference; + final _$function12 = function12?.reference ?? jni$_.jNullReference; + final _$mainLooperHandler = + mainLooperHandler?.reference ?? jni$_.jNullReference; + final _$function01 = function01?.reference ?? jni$_.jNullReference; + return ReplayIntegration.fromReference(_new$3( + _class.reference.pointer, + _id_new$3 as jni$_.JMethodIDPtr, + _$context.pointer, + _$iCurrentDateProvider.pointer, + _$function0.pointer, + _$function1.pointer, + _$function11.pointer, + _$function12.pointer, + _$mainLooperHandler.pointer, + _$function01.pointer) + .reference); + } + + static final _id_new$4 = _class.constructorId( + r'(Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lio/sentry/android/replay/util/MainLooperHandler;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V', + ); + + static final _new$4 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_NewObject') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + jni$_.Pointer, + int, + jni$_.Pointer)>(); + + /// from: `synthetic public void (android.content.Context context, io.sentry.transport.ICurrentDateProvider iCurrentDateProvider, kotlin.jvm.functions.Function0 function0, kotlin.jvm.functions.Function1 function1, kotlin.jvm.functions.Function1 function11, kotlin.jvm.functions.Function1 function12, io.sentry.android.replay.util.MainLooperHandler mainLooperHandler, kotlin.jvm.functions.Function0 function01, int i, kotlin.jvm.internal.DefaultConstructorMarker defaultConstructorMarker)` + /// The returned object must be released after use, by calling the [release] method. + factory ReplayIntegration.new$4( + jni$_.JObject? context, + jni$_.JObject? iCurrentDateProvider, + jni$_.JObject? function0, + jni$_.JObject? function1, + jni$_.JObject? function11, + jni$_.JObject? function12, + jni$_.JObject? mainLooperHandler, + jni$_.JObject? function01, + int i, + jni$_.JObject? defaultConstructorMarker, + ) { + final _$context = context?.reference ?? jni$_.jNullReference; + final _$iCurrentDateProvider = + iCurrentDateProvider?.reference ?? jni$_.jNullReference; + final _$function0 = function0?.reference ?? jni$_.jNullReference; + final _$function1 = function1?.reference ?? jni$_.jNullReference; + final _$function11 = function11?.reference ?? jni$_.jNullReference; + final _$function12 = function12?.reference ?? jni$_.jNullReference; + final _$mainLooperHandler = + mainLooperHandler?.reference ?? jni$_.jNullReference; + final _$function01 = function01?.reference ?? jni$_.jNullReference; + final _$defaultConstructorMarker = + defaultConstructorMarker?.reference ?? jni$_.jNullReference; + return ReplayIntegration.fromReference(_new$4( + _class.reference.pointer, + _id_new$4 as jni$_.JMethodIDPtr, + _$context.pointer, + _$iCurrentDateProvider.pointer, + _$function0.pointer, + _$function1.pointer, + _$function11.pointer, + _$function12.pointer, + _$mainLooperHandler.pointer, + _$function01.pointer, + i, + _$defaultConstructorMarker.pointer) + .reference); + } + + static final _id_getReplayCacheDir = _class.instanceMethodId( + r'getReplayCacheDir', + r'()Ljava/io/File;', + ); + + static final _getReplayCacheDir = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public final java.io.File getReplayCacheDir()` + /// The returned object must be released after use, by calling the [release] method. + jni$_.JObject? getReplayCacheDir() { + return _getReplayCacheDir( + reference.pointer, _id_getReplayCacheDir as jni$_.JMethodIDPtr) + .object(const jni$_.JObjectNullableType()); + } + + static final _id_register = _class.instanceMethodId( + r'register', + r'(Lio/sentry/IScopes;Lio/sentry/SentryOptions;)V', + ); + + static final _register = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer + )>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer)>(); + + /// from: `public void register(io.sentry.IScopes iScopes, io.sentry.SentryOptions sentryOptions)` + void register( + jni$_.JObject iScopes, + jni$_.JObject sentryOptions, + ) { + final _$iScopes = iScopes.reference; + final _$sentryOptions = sentryOptions.reference; + _register(reference.pointer, _id_register as jni$_.JMethodIDPtr, + _$iScopes.pointer, _$sentryOptions.pointer) + .check(); + } + + static final _id_isRecording = _class.instanceMethodId( + r'isRecording', + r'()Z', + ); + + static final _isRecording = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallBooleanMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public boolean isRecording()` + bool isRecording() { + return _isRecording( + reference.pointer, _id_isRecording as jni$_.JMethodIDPtr) + .boolean; + } + + static final _id_start = _class.instanceMethodId( + r'start', + r'()V', + ); + + static final _start = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void start()` + void start() { + _start(reference.pointer, _id_start as jni$_.JMethodIDPtr).check(); + } + + static final _id_resume = _class.instanceMethodId( + r'resume', + r'()V', + ); + + static final _resume = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void resume()` + void resume() { + _resume(reference.pointer, _id_resume as jni$_.JMethodIDPtr).check(); + } + + static final _id_captureReplay = _class.instanceMethodId( + r'captureReplay', + r'(Ljava/lang/Boolean;)V', + ); + + static final _captureReplay = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void captureReplay(java.lang.Boolean boolean)` + void captureReplay( + jni$_.JBoolean? boolean, + ) { + final _$boolean = boolean?.reference ?? jni$_.jNullReference; + _captureReplay(reference.pointer, _id_captureReplay as jni$_.JMethodIDPtr, + _$boolean.pointer) + .check(); + } + + static final _id_getReplayId = _class.instanceMethodId( + r'getReplayId', + r'()Lio/sentry/protocol/SentryId;', + ); + + static final _getReplayId = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public io.sentry.protocol.SentryId getReplayId()` + /// The returned object must be released after use, by calling the [release] method. + jni$_.JObject getReplayId() { + return _getReplayId( + reference.pointer, _id_getReplayId as jni$_.JMethodIDPtr) + .object(const jni$_.JObjectType()); + } + + static final _id_setBreadcrumbConverter = _class.instanceMethodId( + r'setBreadcrumbConverter', + r'(Lio/sentry/ReplayBreadcrumbConverter;)V', + ); + + static final _setBreadcrumbConverter = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void setBreadcrumbConverter(io.sentry.ReplayBreadcrumbConverter replayBreadcrumbConverter)` + void setBreadcrumbConverter( + jni$_.JObject replayBreadcrumbConverter, + ) { + final _$replayBreadcrumbConverter = replayBreadcrumbConverter.reference; + _setBreadcrumbConverter( + reference.pointer, + _id_setBreadcrumbConverter as jni$_.JMethodIDPtr, + _$replayBreadcrumbConverter.pointer) + .check(); + } + + static final _id_getBreadcrumbConverter = _class.instanceMethodId( + r'getBreadcrumbConverter', + r'()Lio/sentry/ReplayBreadcrumbConverter;', + ); + + static final _getBreadcrumbConverter = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public io.sentry.ReplayBreadcrumbConverter getBreadcrumbConverter()` + /// The returned object must be released after use, by calling the [release] method. + jni$_.JObject getBreadcrumbConverter() { + return _getBreadcrumbConverter( + reference.pointer, _id_getBreadcrumbConverter as jni$_.JMethodIDPtr) + .object(const jni$_.JObjectType()); + } + + static final _id_pause = _class.instanceMethodId( + r'pause', + r'()V', + ); + + static final _pause = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void pause()` + void pause() { + _pause(reference.pointer, _id_pause as jni$_.JMethodIDPtr).check(); + } + + static final _id_stop = _class.instanceMethodId( + r'stop', + r'()V', + ); + + static final _stop = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void stop()` + void stop() { + _stop(reference.pointer, _id_stop as jni$_.JMethodIDPtr).check(); + } + + static final _id_onScreenshotRecorded = _class.instanceMethodId( + r'onScreenshotRecorded', + r'(Landroid/graphics/Bitmap;)V', + ); + + static final _onScreenshotRecorded = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onScreenshotRecorded(android.graphics.Bitmap bitmap)` + void onScreenshotRecorded( + Bitmap bitmap, + ) { + final _$bitmap = bitmap.reference; + _onScreenshotRecorded(reference.pointer, + _id_onScreenshotRecorded as jni$_.JMethodIDPtr, _$bitmap.pointer) + .check(); + } + + static final _id_onScreenshotRecorded$1 = _class.instanceMethodId( + r'onScreenshotRecorded', + r'(Ljava/io/File;J)V', + ); + + static final _onScreenshotRecorded$1 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_ + .VarArgs<(jni$_.Pointer, jni$_.Int64)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer, int)>(); + + /// from: `public void onScreenshotRecorded(java.io.File file, long j)` + void onScreenshotRecorded$1( + jni$_.JObject file, + int j, + ) { + final _$file = file.reference; + _onScreenshotRecorded$1(reference.pointer, + _id_onScreenshotRecorded$1 as jni$_.JMethodIDPtr, _$file.pointer, j) + .check(); + } + + static final _id_close = _class.instanceMethodId( + r'close', + r'()V', + ); + + static final _close = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void close()` + void close() { + _close(reference.pointer, _id_close as jni$_.JMethodIDPtr).check(); + } + + static final _id_onConfigurationChanged = _class.instanceMethodId( + r'onConfigurationChanged', + r'(Landroid/content/res/Configuration;)V', + ); + + static final _onConfigurationChanged = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onConfigurationChanged(android.content.res.Configuration configuration)` + void onConfigurationChanged( + jni$_.JObject configuration, + ) { + final _$configuration = configuration.reference; + _onConfigurationChanged( + reference.pointer, + _id_onConfigurationChanged as jni$_.JMethodIDPtr, + _$configuration.pointer) + .check(); + } + + static final _id_onConnectionStatusChanged = _class.instanceMethodId( + r'onConnectionStatusChanged', + r'(Lio/sentry/IConnectionStatusProvider$ConnectionStatus;)V', + ); + + static final _onConnectionStatusChanged = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onConnectionStatusChanged(io.sentry.IConnectionStatusProvider$ConnectionStatus connectionStatus)` + void onConnectionStatusChanged( + jni$_.JObject connectionStatus, + ) { + final _$connectionStatus = connectionStatus.reference; + _onConnectionStatusChanged( + reference.pointer, + _id_onConnectionStatusChanged as jni$_.JMethodIDPtr, + _$connectionStatus.pointer) + .check(); + } + + static final _id_onRateLimitChanged = _class.instanceMethodId( + r'onRateLimitChanged', + r'(Lio/sentry/transport/RateLimiter;)V', + ); + + static final _onRateLimitChanged = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onRateLimitChanged(io.sentry.transport.RateLimiter rateLimiter)` + void onRateLimitChanged( + jni$_.JObject rateLimiter, + ) { + final _$rateLimiter = rateLimiter.reference; + _onRateLimitChanged(reference.pointer, + _id_onRateLimitChanged as jni$_.JMethodIDPtr, _$rateLimiter.pointer) + .check(); + } + + static final _id_onLowMemory = _class.instanceMethodId( + r'onLowMemory', + r'()V', + ); + + static final _onLowMemory = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void onLowMemory()` + void onLowMemory() { + _onLowMemory(reference.pointer, _id_onLowMemory as jni$_.JMethodIDPtr) + .check(); + } + + static final _id_onTouchEvent = _class.instanceMethodId( + r'onTouchEvent', + r'(Landroid/view/MotionEvent;)V', + ); + + static final _onTouchEvent = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onTouchEvent(android.view.MotionEvent motionEvent)` + void onTouchEvent( + jni$_.JObject motionEvent, + ) { + final _$motionEvent = motionEvent.reference; + _onTouchEvent(reference.pointer, _id_onTouchEvent as jni$_.JMethodIDPtr, + _$motionEvent.pointer) + .check(); + } +} + +final class $ReplayIntegration$NullableType + extends jni$_.JObjType { + @jni$_.internal + const $ReplayIntegration$NullableType(); + + @jni$_.internal + @core$_.override + String get signature => r'Lio/sentry/android/replay/ReplayIntegration;'; + + @jni$_.internal + @core$_.override + ReplayIntegration? fromReference(jni$_.JReference reference) => + reference.isNull + ? null + : ReplayIntegration.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectNullableType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => this; + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($ReplayIntegration$NullableType).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($ReplayIntegration$NullableType) && + other is $ReplayIntegration$NullableType; + } +} + +final class $ReplayIntegration$Type extends jni$_.JObjType { + @jni$_.internal + const $ReplayIntegration$Type(); + + @jni$_.internal + @core$_.override + String get signature => r'Lio/sentry/android/replay/ReplayIntegration;'; + + @jni$_.internal + @core$_.override + ReplayIntegration fromReference(jni$_.JReference reference) => + ReplayIntegration.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectNullableType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => + const $ReplayIntegration$NullableType(); + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($ReplayIntegration$Type).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($ReplayIntegration$Type) && + other is $ReplayIntegration$Type; + } +} + +/// from: `io.sentry.flutter.SentryFlutterPlugin$Companion` +class SentryFlutterPlugin$Companion extends jni$_.JObject { + @jni$_.internal + @core$_.override + final jni$_.JObjType $type; + + @jni$_.internal + SentryFlutterPlugin$Companion.fromReference( + jni$_.JReference reference, + ) : $type = type, + super.fromReference(reference); + + static final _class = + jni$_.JClass.forName(r'io/sentry/flutter/SentryFlutterPlugin$Companion'); + + /// The type which includes information such as the signature of this class. + static const nullableType = $SentryFlutterPlugin$Companion$NullableType(); + static const type = $SentryFlutterPlugin$Companion$Type(); + static final _id_privateSentryGetReplayIntegration = _class.instanceMethodId( + r'privateSentryGetReplayIntegration', + r'()Lio/sentry/android/replay/ReplayIntegration;', + ); + + static final _privateSentryGetReplayIntegration = + jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public final io.sentry.android.replay.ReplayIntegration privateSentryGetReplayIntegration()` + /// The returned object must be released after use, by calling the [release] method. + ReplayIntegration? privateSentryGetReplayIntegration() { + return _privateSentryGetReplayIntegration(reference.pointer, + _id_privateSentryGetReplayIntegration as jni$_.JMethodIDPtr) + .object(const $ReplayIntegration$NullableType()); + } + + static final _id_new$ = _class.constructorId( + r'(Lkotlin/jvm/internal/DefaultConstructorMarker;)V', + ); + + static final _new$ = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_NewObject') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `synthetic public void (kotlin.jvm.internal.DefaultConstructorMarker defaultConstructorMarker)` + /// The returned object must be released after use, by calling the [release] method. + factory SentryFlutterPlugin$Companion( + jni$_.JObject? defaultConstructorMarker, + ) { + final _$defaultConstructorMarker = + defaultConstructorMarker?.reference ?? jni$_.jNullReference; + return SentryFlutterPlugin$Companion.fromReference(_new$( + _class.reference.pointer, + _id_new$ as jni$_.JMethodIDPtr, + _$defaultConstructorMarker.pointer) + .reference); + } +} + +final class $SentryFlutterPlugin$Companion$NullableType + extends jni$_.JObjType { + @jni$_.internal + const $SentryFlutterPlugin$Companion$NullableType(); + + @jni$_.internal + @core$_.override + String get signature => r'Lio/sentry/flutter/SentryFlutterPlugin$Companion;'; + + @jni$_.internal + @core$_.override + SentryFlutterPlugin$Companion? fromReference(jni$_.JReference reference) => + reference.isNull + ? null + : SentryFlutterPlugin$Companion.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => this; + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($SentryFlutterPlugin$Companion$NullableType).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($SentryFlutterPlugin$Companion$NullableType) && + other is $SentryFlutterPlugin$Companion$NullableType; + } +} + +final class $SentryFlutterPlugin$Companion$Type + extends jni$_.JObjType { + @jni$_.internal + const $SentryFlutterPlugin$Companion$Type(); + + @jni$_.internal + @core$_.override + String get signature => r'Lio/sentry/flutter/SentryFlutterPlugin$Companion;'; + + @jni$_.internal + @core$_.override + SentryFlutterPlugin$Companion fromReference(jni$_.JReference reference) => + SentryFlutterPlugin$Companion.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => + const $SentryFlutterPlugin$Companion$NullableType(); + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($SentryFlutterPlugin$Companion$Type).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($SentryFlutterPlugin$Companion$Type) && + other is $SentryFlutterPlugin$Companion$Type; + } +} + +/// from: `io.sentry.flutter.SentryFlutterPlugin` +class SentryFlutterPlugin extends jni$_.JObject { + @jni$_.internal + @core$_.override + final jni$_.JObjType $type; + + @jni$_.internal + SentryFlutterPlugin.fromReference( + jni$_.JReference reference, + ) : $type = type, + super.fromReference(reference); + + static final _class = + jni$_.JClass.forName(r'io/sentry/flutter/SentryFlutterPlugin'); + + /// The type which includes information such as the signature of this class. + static const nullableType = $SentryFlutterPlugin$NullableType(); + static const type = $SentryFlutterPlugin$Type(); + static final _id_Companion = _class.staticFieldId( + r'Companion', + r'Lio/sentry/flutter/SentryFlutterPlugin$Companion;', + ); + + /// from: `static public final io.sentry.flutter.SentryFlutterPlugin$Companion Companion` + /// The returned object must be released after use, by calling the [release] method. + static SentryFlutterPlugin$Companion get Companion => + _id_Companion.get(_class, const $SentryFlutterPlugin$Companion$Type()); + + static final _id_new$ = _class.constructorId( + r'()V', + ); + + static final _new$ = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_NewObject') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void ()` + /// The returned object must be released after use, by calling the [release] method. + factory SentryFlutterPlugin() { + return SentryFlutterPlugin.fromReference( + _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr) + .reference); + } + + static final _id_onAttachedToEngine = _class.instanceMethodId( + r'onAttachedToEngine', + r'(Lio/flutter/embedding/engine/plugins/FlutterPlugin$FlutterPluginBinding;)V', + ); + + static final _onAttachedToEngine = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onAttachedToEngine(io.flutter.embedding.engine.plugins.FlutterPlugin$FlutterPluginBinding flutterPluginBinding)` + void onAttachedToEngine( + jni$_.JObject flutterPluginBinding, + ) { + final _$flutterPluginBinding = flutterPluginBinding.reference; + _onAttachedToEngine( + reference.pointer, + _id_onAttachedToEngine as jni$_.JMethodIDPtr, + _$flutterPluginBinding.pointer) + .check(); + } + + static final _id_onMethodCall = _class.instanceMethodId( + r'onMethodCall', + r'(Lio/flutter/plugin/common/MethodCall;Lio/flutter/plugin/common/MethodChannel$Result;)V', + ); + + static final _onMethodCall = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer + )>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer)>(); + + /// from: `public void onMethodCall(io.flutter.plugin.common.MethodCall methodCall, io.flutter.plugin.common.MethodChannel$Result result)` + void onMethodCall( + jni$_.JObject methodCall, + jni$_.JObject result, + ) { + final _$methodCall = methodCall.reference; + final _$result = result.reference; + _onMethodCall(reference.pointer, _id_onMethodCall as jni$_.JMethodIDPtr, + _$methodCall.pointer, _$result.pointer) + .check(); + } + + static final _id_onDetachedFromEngine = _class.instanceMethodId( + r'onDetachedFromEngine', + r'(Lio/flutter/embedding/engine/plugins/FlutterPlugin$FlutterPluginBinding;)V', + ); + + static final _onDetachedFromEngine = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onDetachedFromEngine(io.flutter.embedding.engine.plugins.FlutterPlugin$FlutterPluginBinding flutterPluginBinding)` + void onDetachedFromEngine( + jni$_.JObject flutterPluginBinding, + ) { + final _$flutterPluginBinding = flutterPluginBinding.reference; + _onDetachedFromEngine( + reference.pointer, + _id_onDetachedFromEngine as jni$_.JMethodIDPtr, + _$flutterPluginBinding.pointer) + .check(); + } + + static final _id_onAttachedToActivity = _class.instanceMethodId( + r'onAttachedToActivity', + r'(Lio/flutter/embedding/engine/plugins/activity/ActivityPluginBinding;)V', + ); + + static final _onAttachedToActivity = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onAttachedToActivity(io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding activityPluginBinding)` + void onAttachedToActivity( + jni$_.JObject activityPluginBinding, + ) { + final _$activityPluginBinding = activityPluginBinding.reference; + _onAttachedToActivity( + reference.pointer, + _id_onAttachedToActivity as jni$_.JMethodIDPtr, + _$activityPluginBinding.pointer) + .check(); + } + + static final _id_onDetachedFromActivity = _class.instanceMethodId( + r'onDetachedFromActivity', + r'()V', + ); + + static final _onDetachedFromActivity = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void onDetachedFromActivity()` + void onDetachedFromActivity() { + _onDetachedFromActivity( + reference.pointer, _id_onDetachedFromActivity as jni$_.JMethodIDPtr) + .check(); + } + + static final _id_onReattachedToActivityForConfigChanges = + _class.instanceMethodId( + r'onReattachedToActivityForConfigChanges', + r'(Lio/flutter/embedding/engine/plugins/activity/ActivityPluginBinding;)V', + ); + + static final _onReattachedToActivityForConfigChanges = + jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onReattachedToActivityForConfigChanges(io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding activityPluginBinding)` + void onReattachedToActivityForConfigChanges( + jni$_.JObject activityPluginBinding, + ) { + final _$activityPluginBinding = activityPluginBinding.reference; + _onReattachedToActivityForConfigChanges( + reference.pointer, + _id_onReattachedToActivityForConfigChanges as jni$_.JMethodIDPtr, + _$activityPluginBinding.pointer) + .check(); + } + + static final _id_onDetachedFromActivityForConfigChanges = + _class.instanceMethodId( + r'onDetachedFromActivityForConfigChanges', + r'()V', + ); + + static final _onDetachedFromActivityForConfigChanges = + jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void onDetachedFromActivityForConfigChanges()` + void onDetachedFromActivityForConfigChanges() { + _onDetachedFromActivityForConfigChanges(reference.pointer, + _id_onDetachedFromActivityForConfigChanges as jni$_.JMethodIDPtr) + .check(); + } + + static final _id_privateSentryGetReplayIntegration = _class.staticMethodId( + r'privateSentryGetReplayIntegration', + r'()Lio/sentry/android/replay/ReplayIntegration;', + ); + + static final _privateSentryGetReplayIntegration = + jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `static public final io.sentry.android.replay.ReplayIntegration privateSentryGetReplayIntegration()` + /// The returned object must be released after use, by calling the [release] method. + static ReplayIntegration? privateSentryGetReplayIntegration() { + return _privateSentryGetReplayIntegration(_class.reference.pointer, + _id_privateSentryGetReplayIntegration as jni$_.JMethodIDPtr) + .object(const $ReplayIntegration$NullableType()); + } +} + +final class $SentryFlutterPlugin$NullableType + extends jni$_.JObjType { + @jni$_.internal + const $SentryFlutterPlugin$NullableType(); + + @jni$_.internal + @core$_.override + String get signature => r'Lio/sentry/flutter/SentryFlutterPlugin;'; + + @jni$_.internal + @core$_.override + SentryFlutterPlugin? fromReference(jni$_.JReference reference) => + reference.isNull + ? null + : SentryFlutterPlugin.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectNullableType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => this; + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($SentryFlutterPlugin$NullableType).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($SentryFlutterPlugin$NullableType) && + other is $SentryFlutterPlugin$NullableType; + } +} + +final class $SentryFlutterPlugin$Type + extends jni$_.JObjType { + @jni$_.internal + const $SentryFlutterPlugin$Type(); + + @jni$_.internal + @core$_.override + String get signature => r'Lio/sentry/flutter/SentryFlutterPlugin;'; + + @jni$_.internal + @core$_.override + SentryFlutterPlugin fromReference(jni$_.JReference reference) => + SentryFlutterPlugin.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectNullableType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => + const $SentryFlutterPlugin$NullableType(); + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($SentryFlutterPlugin$Type).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($SentryFlutterPlugin$Type) && + other is $SentryFlutterPlugin$Type; + } +} + +/// from: `android.graphics.Bitmap$CompressFormat` +class Bitmap$CompressFormat extends jni$_.JObject { + @jni$_.internal + @core$_.override + final jni$_.JObjType $type; + + @jni$_.internal + Bitmap$CompressFormat.fromReference( + jni$_.JReference reference, + ) : $type = type, + super.fromReference(reference); + + static final _class = + jni$_.JClass.forName(r'android/graphics/Bitmap$CompressFormat'); + + /// The type which includes information such as the signature of this class. + static const nullableType = $Bitmap$CompressFormat$NullableType(); + static const type = $Bitmap$CompressFormat$Type(); + static final _id_JPEG = _class.staticFieldId( + r'JPEG', + r'Landroid/graphics/Bitmap$CompressFormat;', + ); + + /// from: `static public final android.graphics.Bitmap$CompressFormat JPEG` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$CompressFormat get JPEG => + _id_JPEG.get(_class, const $Bitmap$CompressFormat$Type()); + + static final _id_PNG = _class.staticFieldId( + r'PNG', + r'Landroid/graphics/Bitmap$CompressFormat;', + ); + + /// from: `static public final android.graphics.Bitmap$CompressFormat PNG` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$CompressFormat get PNG => + _id_PNG.get(_class, const $Bitmap$CompressFormat$Type()); + + static final _id_WEBP = _class.staticFieldId( + r'WEBP', + r'Landroid/graphics/Bitmap$CompressFormat;', + ); + + /// from: `static public final android.graphics.Bitmap$CompressFormat WEBP` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$CompressFormat get WEBP => + _id_WEBP.get(_class, const $Bitmap$CompressFormat$Type()); + + static final _id_WEBP_LOSSY = _class.staticFieldId( + r'WEBP_LOSSY', + r'Landroid/graphics/Bitmap$CompressFormat;', + ); + + /// from: `static public final android.graphics.Bitmap$CompressFormat WEBP_LOSSY` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$CompressFormat get WEBP_LOSSY => + _id_WEBP_LOSSY.get(_class, const $Bitmap$CompressFormat$Type()); + + static final _id_WEBP_LOSSLESS = _class.staticFieldId( + r'WEBP_LOSSLESS', + r'Landroid/graphics/Bitmap$CompressFormat;', + ); + + /// from: `static public final android.graphics.Bitmap$CompressFormat WEBP_LOSSLESS` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$CompressFormat get WEBP_LOSSLESS => + _id_WEBP_LOSSLESS.get(_class, const $Bitmap$CompressFormat$Type()); + + static final _id_values = _class.staticMethodId( + r'values', + r'()[Landroid/graphics/Bitmap$CompressFormat;', + ); + + static final _values = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `static public android.graphics.Bitmap$CompressFormat[] values()` + /// The returned object must be released after use, by calling the [release] method. + static jni$_.JArray? values() { + return _values(_class.reference.pointer, _id_values as jni$_.JMethodIDPtr) + .object?>( + const jni$_.JArrayNullableType( + $Bitmap$CompressFormat$NullableType())); + } + + static final _id_valueOf = _class.staticMethodId( + r'valueOf', + r'(Ljava/lang/String;)Landroid/graphics/Bitmap$CompressFormat;', + ); + + static final _valueOf = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap$CompressFormat valueOf(java.lang.String synthetic)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$CompressFormat? valueOf( + jni$_.JString? synthetic, + ) { + final _$synthetic = synthetic?.reference ?? jni$_.jNullReference; + return _valueOf(_class.reference.pointer, _id_valueOf as jni$_.JMethodIDPtr, + _$synthetic.pointer) + .object( + const $Bitmap$CompressFormat$NullableType()); + } +} + +final class $Bitmap$CompressFormat$NullableType + extends jni$_.JObjType { + @jni$_.internal + const $Bitmap$CompressFormat$NullableType(); + + @jni$_.internal + @core$_.override + String get signature => r'Landroid/graphics/Bitmap$CompressFormat;'; + + @jni$_.internal + @core$_.override + Bitmap$CompressFormat? fromReference(jni$_.JReference reference) => + reference.isNull + ? null + : Bitmap$CompressFormat.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectNullableType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => this; + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($Bitmap$CompressFormat$NullableType).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($Bitmap$CompressFormat$NullableType) && + other is $Bitmap$CompressFormat$NullableType; + } +} + +final class $Bitmap$CompressFormat$Type + extends jni$_.JObjType { + @jni$_.internal + const $Bitmap$CompressFormat$Type(); + + @jni$_.internal + @core$_.override + String get signature => r'Landroid/graphics/Bitmap$CompressFormat;'; + + @jni$_.internal + @core$_.override + Bitmap$CompressFormat fromReference(jni$_.JReference reference) => + Bitmap$CompressFormat.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectNullableType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => + const $Bitmap$CompressFormat$NullableType(); + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($Bitmap$CompressFormat$Type).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($Bitmap$CompressFormat$Type) && + other is $Bitmap$CompressFormat$Type; + } +} + +/// from: `android.graphics.Bitmap$Config` +class Bitmap$Config extends jni$_.JObject { + @jni$_.internal + @core$_.override + final jni$_.JObjType $type; + + @jni$_.internal + Bitmap$Config.fromReference( + jni$_.JReference reference, + ) : $type = type, + super.fromReference(reference); + + static final _class = jni$_.JClass.forName(r'android/graphics/Bitmap$Config'); + + /// The type which includes information such as the signature of this class. + static const nullableType = $Bitmap$Config$NullableType(); + static const type = $Bitmap$Config$Type(); + static final _id_ALPHA_8 = _class.staticFieldId( + r'ALPHA_8', + r'Landroid/graphics/Bitmap$Config;', + ); + + /// from: `static public final android.graphics.Bitmap$Config ALPHA_8` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$Config get ALPHA_8 => + _id_ALPHA_8.get(_class, const $Bitmap$Config$Type()); + + static final _id_RGB_565 = _class.staticFieldId( + r'RGB_565', + r'Landroid/graphics/Bitmap$Config;', + ); + + /// from: `static public final android.graphics.Bitmap$Config RGB_565` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$Config get RGB_565 => + _id_RGB_565.get(_class, const $Bitmap$Config$Type()); + + static final _id_ARGB_4444 = _class.staticFieldId( + r'ARGB_4444', + r'Landroid/graphics/Bitmap$Config;', + ); + + /// from: `static public final android.graphics.Bitmap$Config ARGB_4444` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$Config get ARGB_4444 => + _id_ARGB_4444.get(_class, const $Bitmap$Config$Type()); + + static final _id_ARGB_8888 = _class.staticFieldId( + r'ARGB_8888', + r'Landroid/graphics/Bitmap$Config;', + ); + + /// from: `static public final android.graphics.Bitmap$Config ARGB_8888` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$Config get ARGB_8888 => + _id_ARGB_8888.get(_class, const $Bitmap$Config$Type()); + + static final _id_RGBA_F16 = _class.staticFieldId( + r'RGBA_F16', + r'Landroid/graphics/Bitmap$Config;', + ); + + /// from: `static public final android.graphics.Bitmap$Config RGBA_F16` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$Config get RGBA_F16 => + _id_RGBA_F16.get(_class, const $Bitmap$Config$Type()); + + static final _id_HARDWARE = _class.staticFieldId( + r'HARDWARE', + r'Landroid/graphics/Bitmap$Config;', + ); + + /// from: `static public final android.graphics.Bitmap$Config HARDWARE` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$Config get HARDWARE => + _id_HARDWARE.get(_class, const $Bitmap$Config$Type()); + + static final _id_RGBA_1010102 = _class.staticFieldId( + r'RGBA_1010102', + r'Landroid/graphics/Bitmap$Config;', + ); + + /// from: `static public final android.graphics.Bitmap$Config RGBA_1010102` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$Config get RGBA_1010102 => + _id_RGBA_1010102.get(_class, const $Bitmap$Config$Type()); + + static final _id_values = _class.staticMethodId( + r'values', + r'()[Landroid/graphics/Bitmap$Config;', + ); + + static final _values = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `static public android.graphics.Bitmap$Config[] values()` + /// The returned object must be released after use, by calling the [release] method. + static jni$_.JArray? values() { + return _values(_class.reference.pointer, _id_values as jni$_.JMethodIDPtr) + .object?>( + const jni$_.JArrayNullableType( + $Bitmap$Config$NullableType())); + } + + static final _id_valueOf = _class.staticMethodId( + r'valueOf', + r'(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;', + ); + + static final _valueOf = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap$Config valueOf(java.lang.String synthetic)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap$Config? valueOf( + jni$_.JString? synthetic, + ) { + final _$synthetic = synthetic?.reference ?? jni$_.jNullReference; + return _valueOf(_class.reference.pointer, _id_valueOf as jni$_.JMethodIDPtr, + _$synthetic.pointer) + .object(const $Bitmap$Config$NullableType()); + } +} + +final class $Bitmap$Config$NullableType extends jni$_.JObjType { + @jni$_.internal + const $Bitmap$Config$NullableType(); + + @jni$_.internal + @core$_.override + String get signature => r'Landroid/graphics/Bitmap$Config;'; + + @jni$_.internal + @core$_.override + Bitmap$Config? fromReference(jni$_.JReference reference) => reference.isNull + ? null + : Bitmap$Config.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectNullableType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => this; + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($Bitmap$Config$NullableType).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($Bitmap$Config$NullableType) && + other is $Bitmap$Config$NullableType; + } +} + +final class $Bitmap$Config$Type extends jni$_.JObjType { + @jni$_.internal + const $Bitmap$Config$Type(); + + @jni$_.internal + @core$_.override + String get signature => r'Landroid/graphics/Bitmap$Config;'; + + @jni$_.internal + @core$_.override + Bitmap$Config fromReference(jni$_.JReference reference) => + Bitmap$Config.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectNullableType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => + const $Bitmap$Config$NullableType(); + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($Bitmap$Config$Type).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($Bitmap$Config$Type) && + other is $Bitmap$Config$Type; + } +} + +/// from: `android.graphics.Bitmap` +class Bitmap extends jni$_.JObject { + @jni$_.internal + @core$_.override + final jni$_.JObjType $type; + + @jni$_.internal + Bitmap.fromReference( + jni$_.JReference reference, + ) : $type = type, + super.fromReference(reference); + + static final _class = jni$_.JClass.forName(r'android/graphics/Bitmap'); + + /// The type which includes information such as the signature of this class. + static const nullableType = $Bitmap$NullableType(); + static const type = $Bitmap$Type(); + static final _id_CREATOR = _class.staticFieldId( + r'CREATOR', + r'Landroid/os/Parcelable$Creator;', + ); + + /// from: `static public final android.os.Parcelable$Creator CREATOR` + /// The returned object must be released after use, by calling the [release] method. + static jni$_.JObject? get CREATOR => + _id_CREATOR.get(_class, const jni$_.JObjectNullableType()); + + /// from: `static public final int DENSITY_NONE` + static const DENSITY_NONE = 0; + static final _id_getDensity = _class.instanceMethodId( + r'getDensity', + r'()I', + ); + + static final _getDensity = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public int getDensity()` + int getDensity() { + return _getDensity(reference.pointer, _id_getDensity as jni$_.JMethodIDPtr) + .integer; + } + + static final _id_setDensity = _class.instanceMethodId( + r'setDensity', + r'(I)V', + ); + + static final _setDensity = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32,)>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `public void setDensity(int i)` + void setDensity( + int i, + ) { + _setDensity(reference.pointer, _id_setDensity as jni$_.JMethodIDPtr, i) + .check(); + } + + static final _id_reconfigure = _class.instanceMethodId( + r'reconfigure', + r'(IILandroid/graphics/Bitmap$Config;)V', + ); + + static final _reconfigure = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, int, int, jni$_.Pointer)>(); + + /// from: `public void reconfigure(int i, int i1, android.graphics.Bitmap$Config config)` + void reconfigure( + int i, + int i1, + Bitmap$Config? config, + ) { + final _$config = config?.reference ?? jni$_.jNullReference; + _reconfigure(reference.pointer, _id_reconfigure as jni$_.JMethodIDPtr, i, + i1, _$config.pointer) + .check(); + } + + static final _id_setWidth = _class.instanceMethodId( + r'setWidth', + r'(I)V', + ); + + static final _setWidth = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32,)>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `public void setWidth(int i)` + void setWidth( + int i, + ) { + _setWidth(reference.pointer, _id_setWidth as jni$_.JMethodIDPtr, i).check(); + } + + static final _id_setHeight = _class.instanceMethodId( + r'setHeight', + r'(I)V', + ); + + static final _setHeight = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32,)>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `public void setHeight(int i)` + void setHeight( + int i, + ) { + _setHeight(reference.pointer, _id_setHeight as jni$_.JMethodIDPtr, i) + .check(); + } + + static final _id_setConfig = _class.instanceMethodId( + r'setConfig', + r'(Landroid/graphics/Bitmap$Config;)V', + ); + + static final _setConfig = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void setConfig(android.graphics.Bitmap$Config config)` + void setConfig( + Bitmap$Config? config, + ) { + final _$config = config?.reference ?? jni$_.jNullReference; + _setConfig(reference.pointer, _id_setConfig as jni$_.JMethodIDPtr, + _$config.pointer) + .check(); + } + + static final _id_recycle = _class.instanceMethodId( + r'recycle', + r'()V', + ); + + static final _recycle = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void recycle()` + void recycle() { + _recycle(reference.pointer, _id_recycle as jni$_.JMethodIDPtr).check(); + } + + static final _id_isRecycled = _class.instanceMethodId( + r'isRecycled', + r'()Z', + ); + + static final _isRecycled = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallBooleanMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public boolean isRecycled()` + bool isRecycled() { + return _isRecycled(reference.pointer, _id_isRecycled as jni$_.JMethodIDPtr) + .boolean; + } + + static final _id_getGenerationId = _class.instanceMethodId( + r'getGenerationId', + r'()I', + ); + + static final _getGenerationId = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public int getGenerationId()` + int getGenerationId() { + return _getGenerationId( + reference.pointer, _id_getGenerationId as jni$_.JMethodIDPtr) + .integer; + } + + static final _id_copyPixelsToBuffer = _class.instanceMethodId( + r'copyPixelsToBuffer', + r'(Ljava/nio/Buffer;)V', + ); + + static final _copyPixelsToBuffer = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void copyPixelsToBuffer(java.nio.Buffer buffer)` + void copyPixelsToBuffer( + jni$_.JBuffer? buffer, + ) { + final _$buffer = buffer?.reference ?? jni$_.jNullReference; + _copyPixelsToBuffer(reference.pointer, + _id_copyPixelsToBuffer as jni$_.JMethodIDPtr, _$buffer.pointer) + .check(); + } + + static final _id_copyPixelsFromBuffer = _class.instanceMethodId( + r'copyPixelsFromBuffer', + r'(Ljava/nio/Buffer;)V', + ); + + static final _copyPixelsFromBuffer = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void copyPixelsFromBuffer(java.nio.Buffer buffer)` + void copyPixelsFromBuffer( + jni$_.JBuffer? buffer, + ) { + final _$buffer = buffer?.reference ?? jni$_.jNullReference; + _copyPixelsFromBuffer(reference.pointer, + _id_copyPixelsFromBuffer as jni$_.JMethodIDPtr, _$buffer.pointer) + .check(); + } + + static final _id_copy = _class.instanceMethodId( + r'copy', + r'(Landroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;', + ); + + static final _copy = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_ + .VarArgs<(jni$_.Pointer, jni$_.Int32)>)>>( + 'globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer, int)>(); + + /// from: `public android.graphics.Bitmap copy(android.graphics.Bitmap$Config config, boolean z)` + /// The returned object must be released after use, by calling the [release] method. + Bitmap? copy( + Bitmap$Config? config, + bool z, + ) { + final _$config = config?.reference ?? jni$_.jNullReference; + return _copy(reference.pointer, _id_copy as jni$_.JMethodIDPtr, + _$config.pointer, z ? 1 : 0) + .object(const $Bitmap$NullableType()); + } + + static final _id_asShared = _class.instanceMethodId( + r'asShared', + r'()Landroid/graphics/Bitmap;', + ); + + static final _asShared = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public android.graphics.Bitmap asShared()` + /// The returned object must be released after use, by calling the [release] method. + Bitmap? asShared() { + return _asShared(reference.pointer, _id_asShared as jni$_.JMethodIDPtr) + .object(const $Bitmap$NullableType()); + } + + static final _id_wrapHardwareBuffer = _class.staticMethodId( + r'wrapHardwareBuffer', + r'(Landroid/hardware/HardwareBuffer;Landroid/graphics/ColorSpace;)Landroid/graphics/Bitmap;', + ); + + static final _wrapHardwareBuffer = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap wrapHardwareBuffer(android.hardware.HardwareBuffer hardwareBuffer, android.graphics.ColorSpace colorSpace)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? wrapHardwareBuffer( + jni$_.JObject? hardwareBuffer, + jni$_.JObject? colorSpace, + ) { + final _$hardwareBuffer = hardwareBuffer?.reference ?? jni$_.jNullReference; + final _$colorSpace = colorSpace?.reference ?? jni$_.jNullReference; + return _wrapHardwareBuffer( + _class.reference.pointer, + _id_wrapHardwareBuffer as jni$_.JMethodIDPtr, + _$hardwareBuffer.pointer, + _$colorSpace.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createScaledBitmap = _class.staticMethodId( + r'createScaledBitmap', + r'(Landroid/graphics/Bitmap;IIZ)Landroid/graphics/Bitmap;', + ); + + static final _createScaledBitmap = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32 + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer, int, int, int)>(); + + /// from: `static public android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap bitmap, int i, int i1, boolean z)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createScaledBitmap( + Bitmap? bitmap, + int i, + int i1, + bool z, + ) { + final _$bitmap = bitmap?.reference ?? jni$_.jNullReference; + return _createScaledBitmap( + _class.reference.pointer, + _id_createScaledBitmap as jni$_.JMethodIDPtr, + _$bitmap.pointer, + i, + i1, + z ? 1 : 0) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap = _class.staticMethodId( + r'createBitmap', + r'(Landroid/graphics/Bitmap;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(android.graphics.Bitmap bitmap)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap( + Bitmap? bitmap, + ) { + final _$bitmap = bitmap?.reference ?? jni$_.jNullReference; + return _createBitmap(_class.reference.pointer, + _id_createBitmap as jni$_.JMethodIDPtr, _$bitmap.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$1 = _class.staticMethodId( + r'createBitmap', + r'(Landroid/graphics/Bitmap;IIII)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$1 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32 + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + int, + int, + int)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(android.graphics.Bitmap bitmap, int i, int i1, int i2, int i3)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$1( + Bitmap? bitmap, + int i, + int i1, + int i2, + int i3, + ) { + final _$bitmap = bitmap?.reference ?? jni$_.jNullReference; + return _createBitmap$1( + _class.reference.pointer, + _id_createBitmap$1 as jni$_.JMethodIDPtr, + _$bitmap.pointer, + i, + i1, + i2, + i3) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$2 = _class.staticMethodId( + r'createBitmap', + r'(Landroid/graphics/Bitmap;IIIILandroid/graphics/Matrix;Z)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$2 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer, + jni$_.Int32 + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + int, + int, + int, + jni$_.Pointer, + int)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(android.graphics.Bitmap bitmap, int i, int i1, int i2, int i3, android.graphics.Matrix matrix, boolean z)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$2( + Bitmap? bitmap, + int i, + int i1, + int i2, + int i3, + jni$_.JObject? matrix, + bool z, + ) { + final _$bitmap = bitmap?.reference ?? jni$_.jNullReference; + final _$matrix = matrix?.reference ?? jni$_.jNullReference; + return _createBitmap$2( + _class.reference.pointer, + _id_createBitmap$2 as jni$_.JMethodIDPtr, + _$bitmap.pointer, + i, + i1, + i2, + i3, + _$matrix.pointer, + z ? 1 : 0) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$3 = _class.staticMethodId( + r'createBitmap', + r'(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$3 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, int, int, jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(int i, int i1, android.graphics.Bitmap$Config config)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$3( + int i, + int i1, + Bitmap$Config? config, + ) { + final _$config = config?.reference ?? jni$_.jNullReference; + return _createBitmap$3(_class.reference.pointer, + _id_createBitmap$3 as jni$_.JMethodIDPtr, i, i1, _$config.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$4 = _class.staticMethodId( + r'createBitmap', + r'(Landroid/util/DisplayMetrics;IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$4 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + int, + jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(android.util.DisplayMetrics displayMetrics, int i, int i1, android.graphics.Bitmap$Config config)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$4( + jni$_.JObject? displayMetrics, + int i, + int i1, + Bitmap$Config? config, + ) { + final _$displayMetrics = displayMetrics?.reference ?? jni$_.jNullReference; + final _$config = config?.reference ?? jni$_.jNullReference; + return _createBitmap$4( + _class.reference.pointer, + _id_createBitmap$4 as jni$_.JMethodIDPtr, + _$displayMetrics.pointer, + i, + i1, + _$config.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$5 = _class.staticMethodId( + r'createBitmap', + r'(IILandroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$5 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer, + jni$_.Int32 + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, int, int, jni$_.Pointer, int)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(int i, int i1, android.graphics.Bitmap$Config config, boolean z)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$5( + int i, + int i1, + Bitmap$Config? config, + bool z, + ) { + final _$config = config?.reference ?? jni$_.jNullReference; + return _createBitmap$5( + _class.reference.pointer, + _id_createBitmap$5 as jni$_.JMethodIDPtr, + i, + i1, + _$config.pointer, + z ? 1 : 0) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$6 = _class.staticMethodId( + r'createBitmap', + r'(IILandroid/graphics/Bitmap$Config;ZLandroid/graphics/ColorSpace;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$6 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + int, + int, + jni$_.Pointer, + int, + jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(int i, int i1, android.graphics.Bitmap$Config config, boolean z, android.graphics.ColorSpace colorSpace)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$6( + int i, + int i1, + Bitmap$Config? config, + bool z, + jni$_.JObject? colorSpace, + ) { + final _$config = config?.reference ?? jni$_.jNullReference; + final _$colorSpace = colorSpace?.reference ?? jni$_.jNullReference; + return _createBitmap$6( + _class.reference.pointer, + _id_createBitmap$6 as jni$_.JMethodIDPtr, + i, + i1, + _$config.pointer, + z ? 1 : 0, + _$colorSpace.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$7 = _class.staticMethodId( + r'createBitmap', + r'(Landroid/util/DisplayMetrics;IILandroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$7 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer, + jni$_.Int32 + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + int, + jni$_.Pointer, + int)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(android.util.DisplayMetrics displayMetrics, int i, int i1, android.graphics.Bitmap$Config config, boolean z)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$7( + jni$_.JObject? displayMetrics, + int i, + int i1, + Bitmap$Config? config, + bool z, + ) { + final _$displayMetrics = displayMetrics?.reference ?? jni$_.jNullReference; + final _$config = config?.reference ?? jni$_.jNullReference; + return _createBitmap$7( + _class.reference.pointer, + _id_createBitmap$7 as jni$_.JMethodIDPtr, + _$displayMetrics.pointer, + i, + i1, + _$config.pointer, + z ? 1 : 0) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$8 = _class.staticMethodId( + r'createBitmap', + r'(Landroid/util/DisplayMetrics;IILandroid/graphics/Bitmap$Config;ZLandroid/graphics/ColorSpace;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$8 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + int, + jni$_.Pointer, + int, + jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(android.util.DisplayMetrics displayMetrics, int i, int i1, android.graphics.Bitmap$Config config, boolean z, android.graphics.ColorSpace colorSpace)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$8( + jni$_.JObject? displayMetrics, + int i, + int i1, + Bitmap$Config? config, + bool z, + jni$_.JObject? colorSpace, + ) { + final _$displayMetrics = displayMetrics?.reference ?? jni$_.jNullReference; + final _$config = config?.reference ?? jni$_.jNullReference; + final _$colorSpace = colorSpace?.reference ?? jni$_.jNullReference; + return _createBitmap$8( + _class.reference.pointer, + _id_createBitmap$8 as jni$_.JMethodIDPtr, + _$displayMetrics.pointer, + i, + i1, + _$config.pointer, + z ? 1 : 0, + _$colorSpace.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$9 = _class.staticMethodId( + r'createBitmap', + r'([IIIIILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$9 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + int, + int, + int, + jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(int[] is, int i, int i1, int i2, int i3, android.graphics.Bitmap$Config config)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$9( + jni$_.JIntArray? is$, + int i, + int i1, + int i2, + int i3, + Bitmap$Config? config, + ) { + final _$is$ = is$?.reference ?? jni$_.jNullReference; + final _$config = config?.reference ?? jni$_.jNullReference; + return _createBitmap$9( + _class.reference.pointer, + _id_createBitmap$9 as jni$_.JMethodIDPtr, + _$is$.pointer, + i, + i1, + i2, + i3, + _$config.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$10 = _class.staticMethodId( + r'createBitmap', + r'(Landroid/util/DisplayMetrics;[IIIIILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$10 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer, + int, + int, + int, + int, + jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(android.util.DisplayMetrics displayMetrics, int[] is, int i, int i1, int i2, int i3, android.graphics.Bitmap$Config config)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$10( + jni$_.JObject? displayMetrics, + jni$_.JIntArray? is$, + int i, + int i1, + int i2, + int i3, + Bitmap$Config? config, + ) { + final _$displayMetrics = displayMetrics?.reference ?? jni$_.jNullReference; + final _$is$ = is$?.reference ?? jni$_.jNullReference; + final _$config = config?.reference ?? jni$_.jNullReference; + return _createBitmap$10( + _class.reference.pointer, + _id_createBitmap$10 as jni$_.JMethodIDPtr, + _$displayMetrics.pointer, + _$is$.pointer, + i, + i1, + i2, + i3, + _$config.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$11 = _class.staticMethodId( + r'createBitmap', + r'([IIILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$11 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + int, + jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(int[] is, int i, int i1, android.graphics.Bitmap$Config config)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$11( + jni$_.JIntArray? is$, + int i, + int i1, + Bitmap$Config? config, + ) { + final _$is$ = is$?.reference ?? jni$_.jNullReference; + final _$config = config?.reference ?? jni$_.jNullReference; + return _createBitmap$11( + _class.reference.pointer, + _id_createBitmap$11 as jni$_.JMethodIDPtr, + _$is$.pointer, + i, + i1, + _$config.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$12 = _class.staticMethodId( + r'createBitmap', + r'(Landroid/util/DisplayMetrics;[IIILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$12 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer, + int, + int, + jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(android.util.DisplayMetrics displayMetrics, int[] is, int i, int i1, android.graphics.Bitmap$Config config)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$12( + jni$_.JObject? displayMetrics, + jni$_.JIntArray? is$, + int i, + int i1, + Bitmap$Config? config, + ) { + final _$displayMetrics = displayMetrics?.reference ?? jni$_.jNullReference; + final _$is$ = is$?.reference ?? jni$_.jNullReference; + final _$config = config?.reference ?? jni$_.jNullReference; + return _createBitmap$12( + _class.reference.pointer, + _id_createBitmap$12 as jni$_.JMethodIDPtr, + _$displayMetrics.pointer, + _$is$.pointer, + i, + i1, + _$config.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$13 = _class.staticMethodId( + r'createBitmap', + r'(Landroid/graphics/Picture;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$13 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(android.graphics.Picture picture)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$13( + jni$_.JObject? picture, + ) { + final _$picture = picture?.reference ?? jni$_.jNullReference; + return _createBitmap$13(_class.reference.pointer, + _id_createBitmap$13 as jni$_.JMethodIDPtr, _$picture.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_createBitmap$14 = _class.staticMethodId( + r'createBitmap', + r'(Landroid/graphics/Picture;IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;', + ); + + static final _createBitmap$14 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + int, + jni$_.Pointer)>(); + + /// from: `static public android.graphics.Bitmap createBitmap(android.graphics.Picture picture, int i, int i1, android.graphics.Bitmap$Config config)` + /// The returned object must be released after use, by calling the [release] method. + static Bitmap? createBitmap$14( + jni$_.JObject? picture, + int i, + int i1, + Bitmap$Config? config, + ) { + final _$picture = picture?.reference ?? jni$_.jNullReference; + final _$config = config?.reference ?? jni$_.jNullReference; + return _createBitmap$14( + _class.reference.pointer, + _id_createBitmap$14 as jni$_.JMethodIDPtr, + _$picture.pointer, + i, + i1, + _$config.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_getNinePatchChunk = _class.instanceMethodId( + r'getNinePatchChunk', + r'()[B', + ); + + static final _getNinePatchChunk = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public byte[] getNinePatchChunk()` + /// The returned object must be released after use, by calling the [release] method. + jni$_.JByteArray? getNinePatchChunk() { + return _getNinePatchChunk( + reference.pointer, _id_getNinePatchChunk as jni$_.JMethodIDPtr) + .object(const jni$_.JByteArrayNullableType()); + } + + static final _id_compress = _class.instanceMethodId( + r'compress', + r'(Landroid/graphics/Bitmap$CompressFormat;ILjava/io/OutputStream;)Z', + ); + + static final _compress = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Pointer + )>)>>('globalEnv_CallBooleanMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + jni$_.Pointer)>(); + + /// from: `public boolean compress(android.graphics.Bitmap$CompressFormat compressFormat, int i, java.io.OutputStream outputStream)` + bool compress( + Bitmap$CompressFormat? compressFormat, + int i, + jni$_.JObject? outputStream, + ) { + final _$compressFormat = compressFormat?.reference ?? jni$_.jNullReference; + final _$outputStream = outputStream?.reference ?? jni$_.jNullReference; + return _compress(reference.pointer, _id_compress as jni$_.JMethodIDPtr, + _$compressFormat.pointer, i, _$outputStream.pointer) + .boolean; + } + + static final _id_isMutable = _class.instanceMethodId( + r'isMutable', + r'()Z', + ); + + static final _isMutable = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallBooleanMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public boolean isMutable()` + bool isMutable() { + return _isMutable(reference.pointer, _id_isMutable as jni$_.JMethodIDPtr) + .boolean; + } + + static final _id_isPremultiplied = _class.instanceMethodId( + r'isPremultiplied', + r'()Z', + ); + + static final _isPremultiplied = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallBooleanMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public boolean isPremultiplied()` + bool isPremultiplied() { + return _isPremultiplied( + reference.pointer, _id_isPremultiplied as jni$_.JMethodIDPtr) + .boolean; + } + + static final _id_setPremultiplied = _class.instanceMethodId( + r'setPremultiplied', + r'(Z)V', + ); + + static final _setPremultiplied = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32,)>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `public void setPremultiplied(boolean z)` + void setPremultiplied( + bool z, + ) { + _setPremultiplied(reference.pointer, + _id_setPremultiplied as jni$_.JMethodIDPtr, z ? 1 : 0) + .check(); + } + + static final _id_getWidth = _class.instanceMethodId( + r'getWidth', + r'()I', + ); + + static final _getWidth = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public int getWidth()` + int getWidth() { + return _getWidth(reference.pointer, _id_getWidth as jni$_.JMethodIDPtr) + .integer; + } + + static final _id_getHeight = _class.instanceMethodId( + r'getHeight', + r'()I', + ); + + static final _getHeight = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public int getHeight()` + int getHeight() { + return _getHeight(reference.pointer, _id_getHeight as jni$_.JMethodIDPtr) + .integer; + } + + static final _id_getScaledWidth = _class.instanceMethodId( + r'getScaledWidth', + r'(Landroid/graphics/Canvas;)I', + ); + + static final _getScaledWidth = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public int getScaledWidth(android.graphics.Canvas canvas)` + int getScaledWidth( + jni$_.JObject? canvas, + ) { + final _$canvas = canvas?.reference ?? jni$_.jNullReference; + return _getScaledWidth(reference.pointer, + _id_getScaledWidth as jni$_.JMethodIDPtr, _$canvas.pointer) + .integer; + } + + static final _id_getScaledHeight = _class.instanceMethodId( + r'getScaledHeight', + r'(Landroid/graphics/Canvas;)I', + ); + + static final _getScaledHeight = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public int getScaledHeight(android.graphics.Canvas canvas)` + int getScaledHeight( + jni$_.JObject? canvas, + ) { + final _$canvas = canvas?.reference ?? jni$_.jNullReference; + return _getScaledHeight(reference.pointer, + _id_getScaledHeight as jni$_.JMethodIDPtr, _$canvas.pointer) + .integer; + } + + static final _id_getScaledWidth$1 = _class.instanceMethodId( + r'getScaledWidth', + r'(Landroid/util/DisplayMetrics;)I', + ); + + static final _getScaledWidth$1 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public int getScaledWidth(android.util.DisplayMetrics displayMetrics)` + int getScaledWidth$1( + jni$_.JObject? displayMetrics, + ) { + final _$displayMetrics = displayMetrics?.reference ?? jni$_.jNullReference; + return _getScaledWidth$1( + reference.pointer, + _id_getScaledWidth$1 as jni$_.JMethodIDPtr, + _$displayMetrics.pointer) + .integer; + } + + static final _id_getScaledHeight$1 = _class.instanceMethodId( + r'getScaledHeight', + r'(Landroid/util/DisplayMetrics;)I', + ); + + static final _getScaledHeight$1 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public int getScaledHeight(android.util.DisplayMetrics displayMetrics)` + int getScaledHeight$1( + jni$_.JObject? displayMetrics, + ) { + final _$displayMetrics = displayMetrics?.reference ?? jni$_.jNullReference; + return _getScaledHeight$1( + reference.pointer, + _id_getScaledHeight$1 as jni$_.JMethodIDPtr, + _$displayMetrics.pointer) + .integer; + } + + static final _id_getScaledWidth$2 = _class.instanceMethodId( + r'getScaledWidth', + r'(I)I', + ); + + static final _getScaledWidth$2 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32,)>)>>('globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `public int getScaledWidth(int i)` + int getScaledWidth$2( + int i, + ) { + return _getScaledWidth$2( + reference.pointer, _id_getScaledWidth$2 as jni$_.JMethodIDPtr, i) + .integer; + } + + static final _id_getScaledHeight$2 = _class.instanceMethodId( + r'getScaledHeight', + r'(I)I', + ); + + static final _getScaledHeight$2 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32,)>)>>('globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `public int getScaledHeight(int i)` + int getScaledHeight$2( + int i, + ) { + return _getScaledHeight$2( + reference.pointer, _id_getScaledHeight$2 as jni$_.JMethodIDPtr, i) + .integer; + } + + static final _id_getRowBytes = _class.instanceMethodId( + r'getRowBytes', + r'()I', + ); + + static final _getRowBytes = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public int getRowBytes()` + int getRowBytes() { + return _getRowBytes( + reference.pointer, _id_getRowBytes as jni$_.JMethodIDPtr) + .integer; + } + + static final _id_getByteCount = _class.instanceMethodId( + r'getByteCount', + r'()I', + ); + + static final _getByteCount = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public int getByteCount()` + int getByteCount() { + return _getByteCount( + reference.pointer, _id_getByteCount as jni$_.JMethodIDPtr) + .integer; + } + + static final _id_getAllocationByteCount = _class.instanceMethodId( + r'getAllocationByteCount', + r'()I', + ); + + static final _getAllocationByteCount = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public int getAllocationByteCount()` + int getAllocationByteCount() { + return _getAllocationByteCount( + reference.pointer, _id_getAllocationByteCount as jni$_.JMethodIDPtr) + .integer; + } + + static final _id_getConfig = _class.instanceMethodId( + r'getConfig', + r'()Landroid/graphics/Bitmap$Config;', + ); + + static final _getConfig = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public android.graphics.Bitmap$Config getConfig()` + /// The returned object must be released after use, by calling the [release] method. + Bitmap$Config? getConfig() { + return _getConfig(reference.pointer, _id_getConfig as jni$_.JMethodIDPtr) + .object(const $Bitmap$Config$NullableType()); + } + + static final _id_hasAlpha = _class.instanceMethodId( + r'hasAlpha', + r'()Z', + ); + + static final _hasAlpha = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallBooleanMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public boolean hasAlpha()` + bool hasAlpha() { + return _hasAlpha(reference.pointer, _id_hasAlpha as jni$_.JMethodIDPtr) + .boolean; + } + + static final _id_setHasAlpha = _class.instanceMethodId( + r'setHasAlpha', + r'(Z)V', + ); + + static final _setHasAlpha = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32,)>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `public void setHasAlpha(boolean z)` + void setHasAlpha( + bool z, + ) { + _setHasAlpha( + reference.pointer, _id_setHasAlpha as jni$_.JMethodIDPtr, z ? 1 : 0) + .check(); + } + + static final _id_hasMipMap = _class.instanceMethodId( + r'hasMipMap', + r'()Z', + ); + + static final _hasMipMap = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallBooleanMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public boolean hasMipMap()` + bool hasMipMap() { + return _hasMipMap(reference.pointer, _id_hasMipMap as jni$_.JMethodIDPtr) + .boolean; + } + + static final _id_setHasMipMap = _class.instanceMethodId( + r'setHasMipMap', + r'(Z)V', + ); + + static final _setHasMipMap = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32,)>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `public void setHasMipMap(boolean z)` + void setHasMipMap( + bool z, + ) { + _setHasMipMap(reference.pointer, _id_setHasMipMap as jni$_.JMethodIDPtr, + z ? 1 : 0) + .check(); + } + + static final _id_getColorSpace = _class.instanceMethodId( + r'getColorSpace', + r'()Landroid/graphics/ColorSpace;', + ); + + static final _getColorSpace = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public android.graphics.ColorSpace getColorSpace()` + /// The returned object must be released after use, by calling the [release] method. + jni$_.JObject? getColorSpace() { + return _getColorSpace( + reference.pointer, _id_getColorSpace as jni$_.JMethodIDPtr) + .object(const jni$_.JObjectNullableType()); + } + + static final _id_setColorSpace = _class.instanceMethodId( + r'setColorSpace', + r'(Landroid/graphics/ColorSpace;)V', + ); + + static final _setColorSpace = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void setColorSpace(android.graphics.ColorSpace colorSpace)` + void setColorSpace( + jni$_.JObject? colorSpace, + ) { + final _$colorSpace = colorSpace?.reference ?? jni$_.jNullReference; + _setColorSpace(reference.pointer, _id_setColorSpace as jni$_.JMethodIDPtr, + _$colorSpace.pointer) + .check(); + } + + static final _id_hasGainmap = _class.instanceMethodId( + r'hasGainmap', + r'()Z', + ); + + static final _hasGainmap = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallBooleanMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public boolean hasGainmap()` + bool hasGainmap() { + return _hasGainmap(reference.pointer, _id_hasGainmap as jni$_.JMethodIDPtr) + .boolean; + } + + static final _id_getGainmap = _class.instanceMethodId( + r'getGainmap', + r'()Landroid/graphics/Gainmap;', + ); + + static final _getGainmap = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public android.graphics.Gainmap getGainmap()` + /// The returned object must be released after use, by calling the [release] method. + jni$_.JObject? getGainmap() { + return _getGainmap(reference.pointer, _id_getGainmap as jni$_.JMethodIDPtr) + .object(const jni$_.JObjectNullableType()); + } + + static final _id_setGainmap = _class.instanceMethodId( + r'setGainmap', + r'(Landroid/graphics/Gainmap;)V', + ); + + static final _setGainmap = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void setGainmap(android.graphics.Gainmap gainmap)` + void setGainmap( + jni$_.JObject? gainmap, + ) { + final _$gainmap = gainmap?.reference ?? jni$_.jNullReference; + _setGainmap(reference.pointer, _id_setGainmap as jni$_.JMethodIDPtr, + _$gainmap.pointer) + .check(); + } + + static final _id_eraseColor = _class.instanceMethodId( + r'eraseColor', + r'(I)V', + ); + + static final _eraseColor = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32,)>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `public void eraseColor(int i)` + void eraseColor( + int i, + ) { + _eraseColor(reference.pointer, _id_eraseColor as jni$_.JMethodIDPtr, i) + .check(); + } + + static final _id_eraseColor$1 = _class.instanceMethodId( + r'eraseColor', + r'(J)V', + ); + + static final _eraseColor$1 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int64,)>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `public void eraseColor(long j)` + void eraseColor$1( + int j, + ) { + _eraseColor$1(reference.pointer, _id_eraseColor$1 as jni$_.JMethodIDPtr, j) + .check(); + } + + static final _id_getPixel = _class.instanceMethodId( + r'getPixel', + r'(II)I', + ); + + static final _getPixel = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32, jni$_.Int32)>)>>( + 'globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int, int)>(); + + /// from: `public int getPixel(int i, int i1)` + int getPixel( + int i, + int i1, + ) { + return _getPixel( + reference.pointer, _id_getPixel as jni$_.JMethodIDPtr, i, i1) + .integer; + } + + static final _id_getColor = _class.instanceMethodId( + r'getColor', + r'(II)Landroid/graphics/Color;', + ); + + static final _getColor = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32, jni$_.Int32)>)>>( + 'globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int, int)>(); + + /// from: `public android.graphics.Color getColor(int i, int i1)` + /// The returned object must be released after use, by calling the [release] method. + jni$_.JObject? getColor( + int i, + int i1, + ) { + return _getColor( + reference.pointer, _id_getColor as jni$_.JMethodIDPtr, i, i1) + .object(const jni$_.JObjectNullableType()); + } + + static final _id_getPixels = _class.instanceMethodId( + r'getPixels', + r'([IIIIIII)V', + ); + + static final _getPixels = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32 + )>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + int, + int, + int, + int, + int)>(); + + /// from: `public void getPixels(int[] is, int i, int i1, int i2, int i3, int i4, int i5)` + void getPixels( + jni$_.JIntArray? is$, + int i, + int i1, + int i2, + int i3, + int i4, + int i5, + ) { + final _$is$ = is$?.reference ?? jni$_.jNullReference; + _getPixels(reference.pointer, _id_getPixels as jni$_.JMethodIDPtr, + _$is$.pointer, i, i1, i2, i3, i4, i5) + .check(); + } + + static final _id_setPixel = _class.instanceMethodId( + r'setPixel', + r'(III)V', + ); + + static final _setPixel = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Int32, jni$_.Int32, jni$_.Int32)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int, int, int)>(); + + /// from: `public void setPixel(int i, int i1, int i2)` + void setPixel( + int i, + int i1, + int i2, + ) { + _setPixel(reference.pointer, _id_setPixel as jni$_.JMethodIDPtr, i, i1, i2) + .check(); + } + + static final _id_setPixels = _class.instanceMethodId( + r'setPixels', + r'([IIIIIII)V', + ); + + static final _setPixels = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32, + jni$_.Int32 + )>)>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + int, + int, + int, + int, + int, + int)>(); + + /// from: `public void setPixels(int[] is, int i, int i1, int i2, int i3, int i4, int i5)` + void setPixels( + jni$_.JIntArray? is$, + int i, + int i1, + int i2, + int i3, + int i4, + int i5, + ) { + final _$is$ = is$?.reference ?? jni$_.jNullReference; + _setPixels(reference.pointer, _id_setPixels as jni$_.JMethodIDPtr, + _$is$.pointer, i, i1, i2, i3, i4, i5) + .check(); + } + + static final _id_describeContents = _class.instanceMethodId( + r'describeContents', + r'()I', + ); + + static final _describeContents = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallIntMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public int describeContents()` + int describeContents() { + return _describeContents( + reference.pointer, _id_describeContents as jni$_.JMethodIDPtr) + .integer; + } + + static final _id_writeToParcel = _class.instanceMethodId( + r'writeToParcel', + r'(Landroid/os/Parcel;I)V', + ); + + static final _writeToParcel = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_ + .VarArgs<(jni$_.Pointer, jni$_.Int32)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer, int)>(); + + /// from: `public void writeToParcel(android.os.Parcel parcel, int i)` + void writeToParcel( + jni$_.JObject? parcel, + int i, + ) { + final _$parcel = parcel?.reference ?? jni$_.jNullReference; + _writeToParcel(reference.pointer, _id_writeToParcel as jni$_.JMethodIDPtr, + _$parcel.pointer, i) + .check(); + } + + static final _id_extractAlpha = _class.instanceMethodId( + r'extractAlpha', + r'()Landroid/graphics/Bitmap;', + ); + + static final _extractAlpha = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public android.graphics.Bitmap extractAlpha()` + /// The returned object must be released after use, by calling the [release] method. + Bitmap? extractAlpha() { + return _extractAlpha( + reference.pointer, _id_extractAlpha as jni$_.JMethodIDPtr) + .object(const $Bitmap$NullableType()); + } + + static final _id_extractAlpha$1 = _class.instanceMethodId( + r'extractAlpha', + r'(Landroid/graphics/Paint;[I)Landroid/graphics/Bitmap;', + ); + + static final _extractAlpha$1 = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs< + ( + jni$_.Pointer, + jni$_.Pointer + )>)>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.Pointer, + jni$_.Pointer)>(); + + /// from: `public android.graphics.Bitmap extractAlpha(android.graphics.Paint paint, int[] is)` + /// The returned object must be released after use, by calling the [release] method. + Bitmap? extractAlpha$1( + jni$_.JObject? paint, + jni$_.JIntArray? is$, + ) { + final _$paint = paint?.reference ?? jni$_.jNullReference; + final _$is$ = is$?.reference ?? jni$_.jNullReference; + return _extractAlpha$1( + reference.pointer, + _id_extractAlpha$1 as jni$_.JMethodIDPtr, + _$paint.pointer, + _$is$.pointer) + .object(const $Bitmap$NullableType()); + } + + static final _id_sameAs = _class.instanceMethodId( + r'sameAs', + r'(Landroid/graphics/Bitmap;)Z', + ); + + static final _sameAs = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallBooleanMethod') + .asFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public boolean sameAs(android.graphics.Bitmap bitmap)` + bool sameAs( + Bitmap? bitmap, + ) { + final _$bitmap = bitmap?.reference ?? jni$_.jNullReference; + return _sameAs(reference.pointer, _id_sameAs as jni$_.JMethodIDPtr, + _$bitmap.pointer) + .boolean; + } + + static final _id_prepareToDraw = _class.instanceMethodId( + r'prepareToDraw', + r'()V', + ); + + static final _prepareToDraw = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void prepareToDraw()` + void prepareToDraw() { + _prepareToDraw(reference.pointer, _id_prepareToDraw as jni$_.JMethodIDPtr) + .check(); + } + + static final _id_getHardwareBuffer = _class.instanceMethodId( + r'getHardwareBuffer', + r'()Landroid/hardware/HardwareBuffer;', + ); + + static final _getHardwareBuffer = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public android.hardware.HardwareBuffer getHardwareBuffer()` + /// The returned object must be released after use, by calling the [release] method. + jni$_.JObject? getHardwareBuffer() { + return _getHardwareBuffer( + reference.pointer, _id_getHardwareBuffer as jni$_.JMethodIDPtr) + .object(const jni$_.JObjectNullableType()); + } +} + +final class $Bitmap$NullableType extends jni$_.JObjType { + @jni$_.internal + const $Bitmap$NullableType(); + + @jni$_.internal + @core$_.override + String get signature => r'Landroid/graphics/Bitmap;'; + + @jni$_.internal + @core$_.override + Bitmap? fromReference(jni$_.JReference reference) => reference.isNull + ? null + : Bitmap.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectNullableType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => this; + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($Bitmap$NullableType).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($Bitmap$NullableType) && + other is $Bitmap$NullableType; + } +} + +final class $Bitmap$Type extends jni$_.JObjType { + @jni$_.internal + const $Bitmap$Type(); + + @jni$_.internal + @core$_.override + String get signature => r'Landroid/graphics/Bitmap;'; + + @jni$_.internal + @core$_.override + Bitmap fromReference(jni$_.JReference reference) => Bitmap.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JObjType get superType => const jni$_.JObjectNullableType(); + + @jni$_.internal + @core$_.override + jni$_.JObjType get nullableType => const $Bitmap$NullableType(); + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($Bitmap$Type).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($Bitmap$Type) && other is $Bitmap$Type; + } +} diff --git a/flutter/lib/src/native/java/sentry_native_java.dart b/flutter/lib/src/native/java/sentry_native_java.dart index 7aa47f2d73..7ceac09edc 100644 --- a/flutter/lib/src/native/java/sentry_native_java.dart +++ b/flutter/lib/src/native/java/sentry_native_java.dart @@ -17,7 +17,7 @@ class SentryNativeJava extends SentryNativeChannel { Future init(Hub hub) async { // We only need these when replay is enabled (session or error capture) // so let's set it up conditionally. This allows Dart to trim the code. - if (options.experimental.replay.isEnabled) { + if (options.replay.isEnabled) { channel.setMethodCallHandler((call) async { switch (call.method) { case 'ReplayRecorder.start': @@ -29,9 +29,8 @@ class SentryNativeJava extends SentryNativeChannel { height: (call.arguments['height'] as num).toDouble(), frameRate: call.arguments['frameRate'] as int); - _replayRecorder = AndroidReplayRecorder( - config, options, channel, call.arguments['directory'] as String) - ..start(); + _replayRecorder = AndroidReplayRecorder.factory(config, options); + await _replayRecorder!.start(); hub.configureScope((s) { // ignore: invalid_use_of_internal_member diff --git a/flutter/lib/src/native/sentry_native_channel.dart b/flutter/lib/src/native/sentry_native_channel.dart index 313261e831..258afe9f01 100644 --- a/flutter/lib/src/native/sentry_native_channel.dart +++ b/flutter/lib/src/native/sentry_native_channel.dart @@ -67,17 +67,15 @@ class SentryNativeChannel options.appHangTimeoutInterval.inMilliseconds, if (options.proxy != null) 'proxy': options.proxy?.toJson(), 'replay': { - 'quality': options.experimental.replay.quality.name, - 'sessionSampleRate': options.experimental.replay.sessionSampleRate, - 'onErrorSampleRate': options.experimental.replay.onErrorSampleRate, + 'quality': options.replay.quality.name, + 'sessionSampleRate': options.replay.sessionSampleRate, + 'onErrorSampleRate': options.replay.onErrorSampleRate, 'tags': { - 'maskAllText': options.experimental.privacyForReplay.maskAllText, - 'maskAllImages': options.experimental.privacyForReplay.maskAllImages, - 'maskAssetImages': - options.experimental.privacyForReplay.maskAssetImages, - if (options.experimental.privacyForReplay.userMaskingRules.isNotEmpty) - 'maskingRules': options - .experimental.privacyForReplay.userMaskingRules + 'maskAllText': options.privacy.maskAllText, + 'maskAllImages': options.privacy.maskAllImages, + 'maskAssetImages': options.privacy.maskAssetImages, + if (options.privacy.userMaskingRules.isNotEmpty) + 'maskingRules': options.privacy.userMaskingRules .map((rule) => '${rule.name}: ${rule.description}') .toList(growable: false), }, diff --git a/flutter/lib/src/navigation/sentry_display_widget.dart b/flutter/lib/src/navigation/sentry_display_widget.dart deleted file mode 100644 index 77a5ac2882..0000000000 --- a/flutter/lib/src/navigation/sentry_display_widget.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:flutter/cupertino.dart'; - -import '../frame_callback_handler.dart'; -import 'time_to_initial_display_tracker.dart'; - -/// A widget that reports the Time To Initially Displayed (TTID) of its child widget. -/// -/// This widget wraps around another widget to measure and report the time it takes -/// for the child widget to be initially displayed on the screen. This method -/// allows a more accurate measurement than what the default TTID implementation -/// provides. The TTID measurement begins when the route to the widget is pushed and ends -/// when `addPostFramecallback` is triggered. -/// -/// Wrap the widget you want to measure with [SentryDisplayWidget], and ensure that you -/// have set up Sentry's routing instrumentation according to the Sentry documentation. -/// -/// ```dart -/// SentryDisplayWidget( -/// child: MyWidget(), -/// ) -/// ``` -/// -/// Make sure to configure Sentry's routing instrumentation in your app by following -/// the guidelines provided in Sentry's documentation for Flutter integrations: -/// https://docs.sentry.io/platforms/flutter/integrations/routing-instrumentation/ -/// -/// See also: -/// - [Sentry's documentation on Flutter integrations](https://docs.sentry.io/platforms/flutter/) -/// for more information on how to integrate Sentry into your Flutter application. -@Deprecated( - 'Manual TTID tracking is no longer needed - Sentry automatically tracks TTID accurately.' - ' You can safely remove this widget.') -class SentryDisplayWidget extends StatefulWidget { - final Widget child; - final FrameCallbackHandler _frameCallbackHandler; - - SentryDisplayWidget({ - super.key, - required this.child, - @visibleForTesting FrameCallbackHandler? frameCallbackHandler, - }) : _frameCallbackHandler = - frameCallbackHandler ?? DefaultFrameCallbackHandler(); - - @override - _SentryDisplayWidgetState createState() => _SentryDisplayWidgetState(); -} - -// ignore: deprecated_member_use_from_same_package -class _SentryDisplayWidgetState extends State { - @override - void initState() { - super.initState(); - TimeToInitialDisplayTracker().markAsManual(); - - widget._frameCallbackHandler.addPostFrameCallback((_) { - TimeToInitialDisplayTracker().completeTracking(); - }); - } - - @override - Widget build(BuildContext context) { - return widget.child; - } -} diff --git a/flutter/lib/src/navigation/time_to_initial_display_tracker.dart b/flutter/lib/src/navigation/time_to_initial_display_tracker.dart index 3509dc6c4d..690dc433a0 100644 --- a/flutter/lib/src/navigation/time_to_initial_display_tracker.dart +++ b/flutter/lib/src/navigation/time_to_initial_display_tracker.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'package:meta/meta.dart'; - // ignore: implementation_imports import 'package:sentry/src/sentry_tracer.dart'; @@ -26,10 +25,8 @@ class TimeToInitialDisplayTracker { TimeToInitialDisplayTracker._(); FrameCallbackHandler _frameCallbackHandler = DefaultFrameCallbackHandler(); - bool _isManual = false; Completer? _trackingCompleter; DateTime? _endTimestamp; - DateTime? _completeTrackingTimeStamp; final Duration _determineEndtimeTimeout = Duration(seconds: 5); @@ -61,10 +58,7 @@ class TimeToInitialDisplayTracker { startTimestamp: startTimestamp, ); - ttidSpan.origin = origin ?? - (_isManual - ? SentryTraceOrigins.manualUiTimeToDisplay - : SentryTraceOrigins.autoUiTimeToDisplay); + ttidSpan.origin = origin ?? SentryTraceOrigins.autoUiTimeToDisplay; final duration = Duration( milliseconds: _endTimestamp.difference(startTimestamp).inMilliseconds); @@ -87,46 +81,23 @@ class TimeToInitialDisplayTracker { }, ); - // If we already know it's manual we can return the future immediately - if (_isManual) { - final completeTrackingTimeStamp = _completeTrackingTimeStamp; - if (completeTrackingTimeStamp != null) { - // If complete was called before we could call start, complete it here. - _endTimestamp = completeTrackingTimeStamp; - _trackingCompleter?.complete(completeTrackingTimeStamp); - _completeTrackingTimeStamp = null; - } - return future; - } - - // Schedules a check at the end of the frame to determine if the tracking - // should be completed immediately (approximation mode) or deferred (manual mode). _frameCallbackHandler.addPostFrameCallback((_) { - if (!_isManual) { - completeTracking(); - } + completeTracking(); }); return future; } - void markAsManual() { - _isManual = true; - } - void completeTracking() { final timestamp = DateTime.now(); if (_trackingCompleter != null && !_trackingCompleter!.isCompleted) { _endTimestamp = timestamp; _trackingCompleter?.complete(timestamp); - } else { - _completeTrackingTimeStamp = timestamp; } } void clear() { - _isManual = false; _trackingCompleter = null; // We can't clear the ttid end time stamp here, because it might be needed // in the [TimeToFullDisplayTracker] class diff --git a/flutter/lib/src/profiling.dart b/flutter/lib/src/profiling.dart index e2bca9af17..7372aa58b7 100644 --- a/flutter/lib/src/profiling.dart +++ b/flutter/lib/src/profiling.dart @@ -26,12 +26,11 @@ class SentryNativeProfilerFactory implements SentryProfilerFactory { return; } - if (options.platformChecker.isWeb) { + if (options.platform.isWeb) { return; } - if (options.platformChecker.platform.isMacOS || - options.platformChecker.platform.isIOS) { + if (options.platform.isMacOS || options.platform.isIOS) { // ignore: invalid_use_of_internal_member hub.profilerFactory = SentryNativeProfilerFactory(native, options.clock); } diff --git a/flutter/lib/src/renderer/html_renderer.dart b/flutter/lib/src/renderer/html_renderer.dart deleted file mode 100644 index 91d10ae2da..0000000000 --- a/flutter/lib/src/renderer/html_renderer.dart +++ /dev/null @@ -1,13 +0,0 @@ -// ignore: deprecated_member_use -import 'dart:js' as js; - -import 'renderer.dart'; - -FlutterRenderer? getRenderer() { - return isCanvasKitRenderer ? FlutterRenderer.canvasKit : FlutterRenderer.html; -} - -bool get isCanvasKitRenderer { - final flutterCanvasKit = js.context['flutterCanvasKit']; - return flutterCanvasKit != null; -} diff --git a/flutter/lib/src/renderer/renderer.dart b/flutter/lib/src/renderer/renderer.dart index dc9d81276b..42db6e9bf6 100644 --- a/flutter/lib/src/renderer/renderer.dart +++ b/flutter/lib/src/renderer/renderer.dart @@ -1,7 +1,6 @@ import 'package:meta/meta.dart'; import 'unknown_renderer.dart' - if (dart.library.html) 'html_renderer.dart' if (dart.library.js_interop) 'web_renderer.dart' if (dart.library.io) 'io_renderer.dart' as implementation; diff --git a/flutter/lib/src/replay/integration.dart b/flutter/lib/src/replay/integration.dart index 8d57e41755..cf85d53c2e 100644 --- a/flutter/lib/src/replay/integration.dart +++ b/flutter/lib/src/replay/integration.dart @@ -18,7 +18,7 @@ class ReplayIntegration extends Integration { @override FutureOr call(Hub hub, SentryFlutterOptions options) { - final replayOptions = options.experimental.replay; + final replayOptions = options.replay; if (_native.supportsReplay && replayOptions.isEnabled) { options.sdk.addIntegration(replayIntegrationName); diff --git a/flutter/lib/src/replay/replay_recorder.dart b/flutter/lib/src/replay/replay_recorder.dart index bb136f41e5..0deeda52bd 100644 --- a/flutter/lib/src/replay/replay_recorder.dart +++ b/flutter/lib/src/replay/replay_recorder.dart @@ -11,7 +11,7 @@ var _instanceCounter = 0; class ReplayScreenshotRecorder extends ScreenshotRecorder { ReplayScreenshotRecorder(super.config, super.options) : super( - privacyOptions: options.experimental.privacyForReplay, + privacyOptions: options.privacy, logName: 'ReplayRecorder #${++_instanceCounter}'); @override diff --git a/flutter/lib/src/screenshot/recorder.dart b/flutter/lib/src/screenshot/recorder.dart index 93d590a464..363c16cfdd 100644 --- a/flutter/lib/src/screenshot/recorder.dart +++ b/flutter/lib/src/screenshot/recorder.dart @@ -26,21 +26,17 @@ class ScreenshotRecorder { bool _warningLogged = false; late final SentryMaskingConfig? _maskingConfig; - // TODO: remove in the next major release, see recorder_test.dart. - @visibleForTesting - bool get hasWidgetFilter => _maskingConfig != null; - ScreenshotRecorder( this.config, this.options, { SentryPrivacyOptions? privacyOptions, this.logName = 'ScreenshotRecorder', }) { - privacyOptions ??= options.experimental.privacyForScreenshots; + privacyOptions ??= options.privacy; final maskingConfig = - privacyOptions?.buildMaskingConfig(_log, options.platformChecker); - _maskingConfig = (maskingConfig?.length ?? 0) > 0 ? maskingConfig : null; + privacyOptions.buildMaskingConfig(_log, options.runtimeChecker); + _maskingConfig = maskingConfig.length > 0 ? maskingConfig : null; } void _log(SentryLevel level, String message, @@ -118,7 +114,7 @@ class ScreenshotRecorder { List? _obscureSync(_Capture capture) { if (_maskingConfig != null) { - final filter = WidgetFilter(_maskingConfig!, options.logger); + final filter = WidgetFilter(_maskingConfig, options.logger); final colorScheme = capture.context.findColorScheme(); filter.obscure( root: capture.root, diff --git a/flutter/lib/src/sentry_asset_bundle.dart b/flutter/lib/src/sentry_asset_bundle.dart index b4b6c2c905..48aba614dc 100644 --- a/flutter/lib/src/sentry_asset_bundle.dart +++ b/flutter/lib/src/sentry_asset_bundle.dart @@ -78,7 +78,7 @@ class SentryAssetBundle implements AssetBundle { outerSpan, 'loadBuffer', key, - () => _loadBuffer(key), + () => _bundle.loadBuffer(key), updateInnerSpan: (innerSpan) => innerSpan?.setData('file.path', key), ); } @@ -110,14 +110,14 @@ class SentryAssetBundle implements AssetBundle { Future loadStructuredBinaryData( String key, FutureOr Function(ByteData data) parser) { if (!_enableStructuredDataTracing) { - return _loadStructuredBinaryDataWrapper(key, parser); + return _bundle.loadStructuredBinaryData(key, parser); } final outerSpan = _hub.getSpan(); return _wrapLoad( outerSpan, 'loadStructuredBinaryData', key, - () => _loadStructuredBinaryDataWrapper( + () => _bundle.loadStructuredBinaryData( key, (value) => _wrapParser( outerSpan, @@ -256,42 +256,6 @@ class SentryAssetBundle implements AssetBundle { } return uri.pathSegments.isEmpty ? key : uri.pathSegments.last; } - - // Helper: Safe method calls for older flutter versions - - Future _loadBuffer(String key) { - try { - // ignore: return_of_invalid_type - return (_bundle as dynamic).loadBuffer(key); - } on NoSuchMethodError catch (_) { - // The loadBuffer method exists as of Flutter greater than 3.1 - // Previous versions don't have it, but later versions do. - // We can't use `extends` in order to provide this method because this is - // a wrapper and thus the method call must be forwarded. - // On Flutter versions <=3.1 we can't forward this call and - // just catch the error which is thrown. On later version the call gets - // correctly forwarded. - // - // In case of a NoSuchMethodError we just return an empty list - return ImmutableBuffer.fromUint8List(Uint8List.fromList([])); - } - } - - Future _loadStructuredBinaryDataWrapper( - String key, - FutureOr Function(ByteData data) parser, - ) { - // The loadStructuredBinaryData method exists as of Flutter greater than 3.8 - // Previous versions don't have it, but later versions do. - // We can't use `extends` in order to provide this method because this is - // a wrapper and thus the method call must be forwarded. - // On Flutter versions <=3.8 we can't forward this call. - // On later version the call gets correctly forwarded. - // The error doesn't need to handled since it can't be called on earlier versions, - // and it's correctly forwarded on later versions. - return (_bundle as dynamic).loadStructuredBinaryData(key, parser) - as Future; - } } @internal diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 1d2a29548a..1af1e29f1d 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -29,6 +29,7 @@ import 'replay/integration.dart'; import 'utils/platform_dispatcher_wrapper.dart'; import 'version.dart'; import 'view_hierarchy/view_hierarchy_integration.dart'; +import 'web/javascript_transport.dart'; /// Configuration options callback typedef FlutterOptionsConfiguration = FutureOr Function( @@ -63,7 +64,7 @@ mixin SentryFlutter { // ignore: invalid_use_of_internal_member sentrySetupStartTime ??= options.clock(); - if (options.platformChecker.hasNativeIntegration) { + if (options.platform.supportsNativeIntegration) { _native = createBinding(options); } @@ -73,10 +74,9 @@ mixin SentryFlutter { // Flutter Web doesn't capture [Future] errors if using [PlatformDispatcher.onError] and not // the [runZonedGuarded]. // likely due to https://github.com/flutter/flutter/issues/100277 - final bool isOnErrorSupported = - !options.platformChecker.isWeb && wrapper.isOnErrorSupported(options); + final isOnErrorSupported = !options.platform.isWeb; - final bool isRootZone = options.platformChecker.isRootZone; + final bool isRootZone = options.runtimeChecker.isRootZone; // If onError is not supported and no custom zone exists, use runZonedGuarded to capture errors. final bool useRunZonedGuarded = !isOnErrorSupported && isRootZone; @@ -126,14 +126,13 @@ mixin SentryFlutter { // Not all platforms have a native integration. if (_native != null) { if (_native!.supportsCaptureEnvelope) { - // Sentry's native web integration is only enabled when enableSentryJs=true. - // Transport configuration happens in web_integration because the configuration - // options aren't available until after the options callback executes. - if (!options.platformChecker.isWeb) { + if (options.platform.isWeb) { + options.transport = JavascriptTransport(_native!, options); + } else { options.transport = FileSystemTransport(_native!, options); } } - if (!options.platformChecker.isWeb) { + if (!options.platform.isWeb) { options.addScopeObserver(NativeScopeObserver(_native!)); } } @@ -142,7 +141,7 @@ mixin SentryFlutter { options.addEventProcessor(WidgetEventProcessor()); options.addEventProcessor(UrlFilterEventProcessor(options)); - if (options.platformChecker.platform.isAndroid) { + if (options.platform.isAndroid) { options.addEventProcessor( AndroidPlatformExceptionEventProcessor(options), ); @@ -160,7 +159,7 @@ mixin SentryFlutter { bool isOnErrorSupported, ) { final integrations = []; - final platformChecker = options.platformChecker; + final platform = options.platform; // Will call WidgetsFlutterBinding.ensureInitialized() before all other integrations. integrations.add(WidgetsFlutterBindingIntegration()); @@ -181,7 +180,7 @@ mixin SentryFlutter { final native = _native; if (native != null) { integrations.add(createSdkIntegration(native)); - if (!platformChecker.isWeb) { + if (!platform.isWeb) { if (native.supportsLoadContexts) { integrations.add(LoadContextsIntegration(native)); } @@ -199,11 +198,11 @@ mixin SentryFlutter { } final renderer = options.rendererWrapper.getRenderer(); - if (!platformChecker.isWeb || renderer == FlutterRenderer.canvasKit) { + if (!platform.isWeb || renderer == FlutterRenderer.canvasKit) { integrations.add(ScreenshotIntegration()); } - if (platformChecker.isWeb) { + if (platform.isWeb) { integrations.add(ConnectivityIntegration()); } @@ -230,20 +229,6 @@ mixin SentryFlutter { }; } - /// Manually set when your app finished startup. Make sure to set - /// [SentryFlutterOptions.autoAppStart] to false on init. The timeout duration - /// for this to work is 10 seconds. - @Deprecated( - 'Will be removed in v9. This functionality will not be supported anymore.') - static void setAppStartEnd(DateTime appStartEnd) { - // ignore: invalid_use_of_internal_member - final integrations = Sentry.currentHub.options.integrations - .whereType(); - for (final integration in integrations) { - integration.appStartEnd = appStartEnd; - } - } - static void _setSdk(SentryFlutterOptions options) { // overwrite sdk info with current flutter sdk final sdk = SdkVersion( diff --git a/flutter/lib/src/sentry_flutter_options.dart b/flutter/lib/src/sentry_flutter_options.dart index f8d5ba06b9..4c9d8ea97e 100644 --- a/flutter/lib/src/sentry_flutter_options.dart +++ b/flutter/lib/src/sentry_flutter_options.dart @@ -1,7 +1,5 @@ import 'dart:async'; -import 'package:file/file.dart'; -import 'package:file/local.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart' as meta; @@ -12,7 +10,6 @@ import 'event_processor/screenshot_event_processor.dart'; import 'navigation/time_to_display_tracker.dart'; import 'renderer/renderer.dart'; import 'screenshot/sentry_screenshot_quality.dart'; -import 'sentry_flutter.dart'; import 'sentry_privacy_options.dart'; import 'sentry_replay_options.dart'; import 'user_interaction/sentry_user_interaction_widget.dart'; @@ -21,7 +18,7 @@ import 'user_interaction/sentry_user_interaction_widget.dart'; /// Note that some of these options require native Sentry integration, which is /// not available on all platforms. class SentryFlutterOptions extends SentryOptions { - SentryFlutterOptions({super.dsn, super.checker}) { + SentryFlutterOptions({super.dsn, super.platform, super.checker}) { enableBreadcrumbTrackingForCurrentPlatform(); } @@ -175,14 +172,6 @@ class SentryFlutterOptions extends SentryOptions { /// Enable auto performance tracking by default. bool enableAutoPerformanceTracing = true; - /// Automatically track app start measurement and send it with the - /// first transaction. Set to false when configuring option to disable or if - /// you want to set the end time of app startup manually using - /// [SentryFlutter.setAppStartEnd]. - @Deprecated( - 'Will be removed in v9. In order to disable app starts disable it via option.removeIntegration(...) instead') - bool autoAppStart = true; - /// Automatically attaches a screenshot when capturing an error or exception. /// /// Requires adding the [SentryWidget] to the widget tree. @@ -194,14 +183,6 @@ class SentryFlutterOptions extends SentryOptions { /// The quality of the attached screenshot SentryScreenshotQuality screenshotQuality = SentryScreenshotQuality.high; - /// Only attach a screenshot when the app is resumed. - /// See https://docs.sentry.io/platforms/flutter/troubleshooting/#screenshot-integration-background-crash - bool attachScreenshotOnlyWhenResumed = false; - - @Deprecated( - 'Will be removed in a future version. Use [beforeCaptureScreenshot] instead') - BeforeScreenshotCallback? beforeScreenshot; - /// Sets a callback which is executed before capturing screenshots. Only /// relevant if `attachScreenshot` is set to true. When false is returned /// from the function, no screenshot will be attached. @@ -303,12 +284,12 @@ class SentryFlutterOptions extends SentryOptions { /// you must use `SentryWidgetsFlutterBinding.ensureInitialized()` instead. bool enableFramesTracking = true; - /// Controls initialization of the Sentry Javascript SDK on web platforms. - /// When enabled and [autoInitializeNativeSdk] is true, loads and initializes - /// the JS SDK in the document head. - /// - /// Defaults to `false` - bool enableSentryJs = false; + /// Replay recording configuration. + final replay = SentryReplayOptions(); + + /// Privacy configuration for masking sensitive data in screenshots and Session Replay. + /// Screen content masking is enabled by default. + final privacy = SentryPrivacyOptions(); /// By using this, you are disabling native [Breadcrumb] tracking and instead /// you are just tracking [Breadcrumb]s which result from events available @@ -350,7 +331,7 @@ class SentryFlutterOptions extends SentryOptions { /// available in the Flutter environment. This way you get more detailed /// information where available. void enableBreadcrumbTrackingForCurrentPlatform() { - if (platformChecker.hasNativeIntegration) { + if (platform.supportsNativeIntegration) { useNativeBreadcrumbTracking(); } else { useFlutterBreadcrumbTracking(); @@ -394,56 +375,8 @@ class SentryFlutterOptions extends SentryOptions { @override // ignore: invalid_use_of_internal_member set automatedTestMode(bool value) => super.automatedTestMode = value; - - @meta.internal - FileSystem fileSystem = LocalFileSystem(); - - /// Configuration of experimental features that may change or be removed - /// without prior notice. Additionally, these features may not be ready for - /// production use yet. - @meta.experimental - final experimental = _SentryFlutterExperimentalOptions(); } -class _SentryFlutterExperimentalOptions { - /// Replay recording configuration. - final replay = SentryReplayOptions(); - - /// Privacy configuration for masking sensitive data in screenshots and Session Replay. - /// Screen content masking is: - /// - enabled by default for SessionReplay - /// - disabled by default for screenshots captured with events. - /// In order to mask screenshots captured with events, access or change - /// this property in your application: `options.experimental.privacy`. - /// Doing so will indicate that you want to configure privacy settings and - /// will enable screenshot masking alongside the default replay masking. - /// Note: this will change in a future SDK major release to enable screenshot - /// masking by default for all captures. - SentryPrivacyOptions get privacy { - // If the user explicitly sets the privacy setting, we use that. - // Otherwise, we use the default settings, which is no masking for screenshots - // and full masking for session replay. - // This property must only by accessed by user code otherwise it defeats the purpose. - _privacy ??= SentryPrivacyOptions(); - return _privacy!; - } - - /// TODO: remove when default masking value are synced with SS & SR in the next major release - SentryPrivacyOptions? _privacy; - - @meta.internal - SentryPrivacyOptions? get privacyForScreenshots => _privacy; - - @meta.internal - SentryPrivacyOptions get privacyForReplay => - _privacy ?? SentryPrivacyOptions(); -} - -@Deprecated( - 'Will be removed in a future version. Use [BeforeCaptureCallback] instead') -typedef BeforeScreenshotCallback = FutureOr Function(SentryEvent event, - {Hint? hint}); - /// A callback which can be used to suppress capturing of screenshots. /// It's called in [ScreenshotEventProcessor] if screenshots are enabled. /// This gives more fine-grained control over when capturing should be performed, diff --git a/flutter/lib/src/sentry_privacy_options.dart b/flutter/lib/src/sentry_privacy_options.dart index f620a72428..138494571a 100644 --- a/flutter/lib/src/sentry_privacy_options.dart +++ b/flutter/lib/src/sentry_privacy_options.dart @@ -11,17 +11,14 @@ class SentryPrivacyOptions { /// Mask all text content. Draws a rectangle of text bounds with text color /// on top. Currently, only [Text] and [EditableText] Widgets are masked. /// Default is enabled. - @experimental var maskAllText = true; /// Mask content of all images. Draws a rectangle of image bounds with image's /// dominant color on top. Currently, only [Image] widgets are masked. /// Default is enabled (except for asset images, see [maskAssetImages]). - @experimental var maskAllImages = true; /// Redact asset images coming from the root asset bundle. - @experimental var maskAssetImages = false; final _userMaskingRules = []; @@ -31,7 +28,7 @@ class SentryPrivacyOptions { @internal SentryMaskingConfig buildMaskingConfig( - SentryLogger logger, PlatformChecker platform) { + SentryLogger logger, RuntimeChecker runtimeChecker) { // First, we collect rules defined by the user (so they're applied first). final rules = _userMaskingRules.toList(); @@ -76,15 +73,10 @@ class SentryPrivacyOptions { // In Debug mode, check if users explicitly mask (or unmask) widgets that // look like they should be masked, e.g. Videos, WebViews, etc. - if (platform.isDebugMode()) { + if (runtimeChecker.isDebugMode()) { final regexp = RegExp('video|webview|password|pinput|camera|chart', caseSensitive: false); - // Note: the following line just makes sure if the option is renamed, - // someone will notice that there is a string that needs updating too. - SentryFlutterOptions().experimental.privacy; - final optionsName = 'options.experimental.privacy'; - rules.add(SentryMaskingCustomRule( callback: (Element element, Widget widget) { final type = widget.runtimeType.toString(); @@ -96,9 +88,9 @@ class SentryPrivacyOptions { 'widget comes from a third-party plugin or your code, Sentry ' "doesn't recognize it and can't reliably mask it in release " 'builds (due to obfuscation). ' - 'Please mask it explicitly using $optionsName.mask<$type>(). ' + 'Please mask it explicitly using options.privacy.mask<$type>(). ' 'If you want to silence this warning and keep the widget ' - 'visible in captures, you can use $optionsName.unmask<$type>(). ' + 'visible in captures, you can use options.privacy.unmask<$type>(). ' 'Note: the RegExp matched is: $regexp (case insensitive).'); } return SentryMaskingDecision.continueProcessing; diff --git a/flutter/lib/src/sentry_replay_options.dart b/flutter/lib/src/sentry_replay_options.dart index fd9260129a..4075085da9 100644 --- a/flutter/lib/src/sentry_replay_options.dart +++ b/flutter/lib/src/sentry_replay_options.dart @@ -2,8 +2,7 @@ import 'package:meta/meta.dart'; import 'replay/replay_quality.dart'; -/// Configuration of the experimental replay feature. -@experimental +/// Configuration of the replay feature. class SentryReplayOptions { double? _sessionSampleRate; diff --git a/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart b/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart index 1b8dc2fb16..a9fc134fcf 100644 --- a/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart +++ b/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart @@ -620,21 +620,6 @@ class _SentryUserInteractionWidgetState if (element == null) { return false; } - try { - // ignore: return_of_invalid_type - return (element as dynamic).mounted; - } on NoSuchMethodError catch (_) { - // mounted checks if the widget is not null. - - try { - // Flutter 3.0.0 does `_widget!` and if `_widget` is null it throws. - - // ignore: unnecessary_null_comparison - return element.widget != null; - } catch (_) { - // if it throws, the `_widget` is null and not mounted. - return false; - } - } + return element.mounted; } } diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index c63e7b8ae9..7f3de296b3 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.14.0'; +const String sdkVersion = '9.0.0-alpha.1'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/lib/src/view_hierarchy/view_hierarchy_integration.dart b/flutter/lib/src/view_hierarchy/view_hierarchy_integration.dart index a86f380f08..c17d179cc1 100644 --- a/flutter/lib/src/view_hierarchy/view_hierarchy_integration.dart +++ b/flutter/lib/src/view_hierarchy/view_hierarchy_integration.dart @@ -1,7 +1,7 @@ import '../../sentry_flutter.dart'; import 'view_hierarchy_event_processor.dart'; -/// A [Integration] that renders an ASCII represention of the entire view +/// A [Integration] that renders an ASCII representation of the entire view /// hierarchy of the application when an error happens and includes it as an /// attachment to the [Hint]. class SentryViewHierarchyIntegration @@ -13,7 +13,7 @@ class SentryViewHierarchyIntegration void call(Hub hub, SentryFlutterOptions options) { // View hierarchy is always minified on Web and we don't support // symbolication of source maps for view hierarchy yet. - if (!options.attachViewHierarchy || options.platformChecker.isWeb) { + if (!options.attachViewHierarchy || options.platform.isWeb) { return; } _options = options; diff --git a/flutter/lib/src/web/html_sentry_js_binding.dart b/flutter/lib/src/web/html_sentry_js_binding.dart deleted file mode 100644 index 840e48a2a3..0000000000 --- a/flutter/lib/src/web/html_sentry_js_binding.dart +++ /dev/null @@ -1,65 +0,0 @@ -// Will be removed in v9 -// ignore: deprecated_member_use -import 'dart:js'; - -import 'package:flutter/cupertino.dart'; - -import 'sentry_js_binding.dart'; - -SentryJsBinding createJsBinding() { - return HtmlSentryJsBinding(); -} - -class HtmlSentryJsBinding implements SentryJsBinding { - HtmlSentryJsBinding({JsObject? sentry}) : _sentry = sentry; - - JsObject? _sentry; - dynamic _client; - - @override - void init(Map options) { - if (options['defaultIntegrations'] != null) { - options['defaultIntegrations'] = options['defaultIntegrations'] - .map((String integration) => _createIntegration(integration)); - } - - _sentry ??= context['Sentry'] as JsObject; - _sentry!.callMethod('init', [JsObject.jsify(options)]); - _client = _sentry!.callMethod('getClient'); - } - - JsObject? _createIntegration(String integration) { - switch (integration) { - case SentryJsIntegrationName.globalHandlers: - case SentryJsIntegrationName.dedupe: - final jsIntegration = _sentry?.callMethod(integration, []); - return jsIntegration is JsObject ? jsIntegration : null; - default: - return null; - } - } - - @override - void close() { - if (_sentry != null) { - _sentry?.callMethod('close'); - _sentry = null; - context['Sentry'] = null; - } - } - - @override - void captureEnvelope(List envelope) { - if (_client != null) { - _client.callMethod('sendEnvelope', [JsObject.jsify(envelope)]); - } - } - - @visibleForTesting - @override - getJsOptions() { - // newest flutter version removed dartify from JsObject - // we will remove this file in v9 anyway - return null; - } -} diff --git a/flutter/lib/src/web/script_loader/html_script_dom_api.dart b/flutter/lib/src/web/script_loader/html_script_dom_api.dart deleted file mode 100644 index 233376eae3..0000000000 --- a/flutter/lib/src/web/script_loader/html_script_dom_api.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'dart:async'; -// ignore: deprecated_member_use -import 'dart:html'; -// ignore: deprecated_member_use -import 'dart:js_util' as js_util; - -import '../../../sentry_flutter.dart'; -import 'script_dom_api.dart'; -import 'sentry_script_loader.dart'; - -Future loadScript(String src, SentryOptions options, - {String? integrity, - String trustedTypePolicyName = defaultTrustedPolicyName}) { - final completer = Completer(); - - final script = ScriptElement() - ..crossOrigin = 'anonymous' - ..onLoad.listen((_) => completer.complete()) - ..onError.listen((event) => completer.completeError('Failed to load $src')); - - TrustedScriptUrl? trustedUrl; - - // If TrustedTypes are available, prepare a trusted URL - final trustedTypes = js_util.getProperty(window, 'trustedTypes'); - if (trustedTypes != null) { - try { - final policy = - js_util.callMethod(trustedTypes as Object, 'createPolicy', [ - trustedTypePolicyName, - js_util.jsify({ - 'createScriptURL': (String url) => src, - }) - ]); - trustedUrl = - js_util.callMethod(policy as Object, 'createScriptURL', [src]); - } catch (e) { - // will be caught by loadWebSdk - throw TrustedTypesException(); - } - } - - if (trustedUrl != null) { - js_util.setProperty(script, 'src', trustedUrl); - } else { - script.src = src; - } - - if (integrity != null) { - script.integrity = integrity; - } - - // JS SDK needs to be loaded before everything else - final head = document.head; - if (head != null) { - if (head.hasChildNodes()) { - head.insertBefore(script, head.firstChild); - } else { - head.append(script); - } - } - return completer.future; -} - -class _ScriptElement implements SentryScriptElement { - final ScriptElement element; - - _ScriptElement(this.element); - - @override - void remove() { - element.remove(); - } - - @override - String get src => element.src; - - @override - String? get integrity => element.integrity; -} - -List fetchScripts(String query) { - final scripts = document.querySelectorAll(query); - return scripts - .map((script) => _ScriptElement(script as ScriptElement)) - .toList(); -} diff --git a/flutter/lib/src/web/script_loader/script_dom_api.dart b/flutter/lib/src/web/script_loader/script_dom_api.dart index bca967d4d3..db557f5b3f 100644 --- a/flutter/lib/src/web/script_loader/script_dom_api.dart +++ b/flutter/lib/src/web/script_loader/script_dom_api.dart @@ -1,7 +1,6 @@ import 'package:meta/meta.dart'; export 'noop_script_dom_api.dart' - if (dart.library.html) 'html_script_dom_api.dart' if (dart.library.js_interop) 'web_script_dom_api.dart'; @internal diff --git a/flutter/lib/src/web/script_loader/sentry_script_loader.dart b/flutter/lib/src/web/script_loader/sentry_script_loader.dart index 0c21d7a144..621f84e51b 100644 --- a/flutter/lib/src/web/script_loader/sentry_script_loader.dart +++ b/flutter/lib/src/web/script_loader/sentry_script_loader.dart @@ -57,7 +57,7 @@ class SentryScriptLoader { } Future close() async { - final scriptsToRemove = _options.platformChecker.isReleaseMode() + final scriptsToRemove = _options.runtimeChecker.isReleaseMode() ? productionScripts : debugScripts; diff --git a/flutter/lib/src/web/script_loader/web_script_dom_api.dart b/flutter/lib/src/web/script_loader/web_script_dom_api.dart index ef02adabe1..dba089b2ba 100644 --- a/flutter/lib/src/web/script_loader/web_script_dom_api.dart +++ b/flutter/lib/src/web/script_loader/web_script_dom_api.dart @@ -1,10 +1,7 @@ import 'dart:async'; import 'dart:js_interop'; import 'dart:js_interop_unsafe'; - -// ignore: depend_on_referenced_packages import 'package:web/web.dart'; - import '../../../sentry_flutter.dart'; import 'script_dom_api.dart'; import 'sentry_script_loader.dart'; diff --git a/flutter/lib/src/web/sentry_js_binding.dart b/flutter/lib/src/web/sentry_js_binding.dart index 79b92af849..4e54a619e8 100644 --- a/flutter/lib/src/web/sentry_js_binding.dart +++ b/flutter/lib/src/web/sentry_js_binding.dart @@ -1,7 +1,6 @@ import 'package:flutter/cupertino.dart'; export 'noop_sentry_js_binding.dart' - if (dart.library.html) 'html_sentry_js_binding.dart' if (dart.library.js_interop) 'web_sentry_js_binding.dart'; abstract class SentryJsBinding { diff --git a/flutter/microbenchmarks/lib/main.dart b/flutter/microbenchmarks/lib/main.dart index 968cfb92f8..27471fb732 100644 --- a/flutter/microbenchmarks/lib/main.dart +++ b/flutter/microbenchmarks/lib/main.dart @@ -1,16 +1,31 @@ import 'dart:io'; import 'src/image_bench.dart' as image_bench; import 'src/memory_bench.dart' as memory_bench; +import 'src/jni_bench.dart' as jni_bench; typedef BenchmarkSet = (String name, Future Function() callback); +const filter = String.fromEnvironment("FILTER"); + Future main() async { final benchmarks = [ ('Image', image_bench.execute), ('Memory', memory_bench.execute), + if (Platform.isAndroid) ('JNI', jni_bench.execute), ]; + RegExp? filterRegexp; + if (filter.isNotEmpty) { + print('Filtering benchmarks with "$filter"'); + filterRegexp = RegExp(filter, caseSensitive: false); + } + for (final benchmark in benchmarks) { + if (filterRegexp != null && !filterRegexp.hasMatch(benchmark.$1)) { + print('BenchmarkSet ${benchmark.$1}: skipped due to filter'); + continue; + } + final watch = Stopwatch()..start(); print('BenchmarkSet ${benchmark.$1}: starting'); await benchmark.$2.call(); diff --git a/flutter/microbenchmarks/lib/src/jni_bench.dart b/flutter/microbenchmarks/lib/src/jni_bench.dart new file mode 100644 index 0000000000..4a841bb6c0 --- /dev/null +++ b/flutter/microbenchmarks/lib/src/jni_bench.dart @@ -0,0 +1,95 @@ +import 'dart:ffi'; +import 'dart:math'; + +import 'package:jni/jni.dart'; +import 'package:benchmarking/benchmarking.dart'; +import 'package:flutter/foundation.dart'; + +Future execute() async { + final worksets = [ + _WorkSet(10 * 1000), + _WorkSet(1000 * 1000), + _WorkSet(10 * 1000 * 1000), + ]; + + // For baseline + syncBenchmark('JByteBuffer.release()', () { + JByteBuffer.allocateDirect(1).release(); + }).report(); + + for (var workset in worksets) { + syncBenchmark('JByteBuffer.fromList(${workset.size})', () { + final jBuffer = JByteBuffer.fromList(workset.data); + jBuffer.release(); + }).report(); + + syncBenchmark('JByteBuffer.allocatedDirect(${workset.size})', () { + final jBuffer = JByteBuffer.allocateDirect(workset.size); + jBuffer.release(); + }).report(); + + syncBenchmark('JByteBuffer.allocatedDirect(${workset.size}) + memcpy', () { + final jBuffer = JByteBuffer.allocateDirect(workset.size); + final jData = jBuffer._asUint8ListUnsafe(); + memcpy(jData.address, workset.data.address, workset.size); + jBuffer.release(); + }).report(); + } +} + +class _WorkSet { + static final rand = Random(); + final int size; + late final Uint8List data; + + _WorkSet(this.size) { + // Randomized size prevents loop optimizations of constant sized loops. Just in case... + + data = Uint8List.fromList( + List.generate(size, (_) => rand.nextInt(size) % 256)); + } +} + +// Copied over from package:jni due to visibility +extension on JByteBuffer { + Uint8List _asUint8ListUnsafe() { + _ensureIsDirect(); + final address = _directBufferAddress(); + final capacity = _directBufferCapacity(); + return address.cast().asTypedList(capacity); + } + + Pointer _directBufferAddress() { + final address = Jni.env.GetDirectBufferAddress(reference.pointer); + if (address == nullptr) { + throw StateError( + 'The memory region is undefined or ' + 'direct buffer access is not supported by this JVM.', + ); + } + return address; + } + + int _directBufferCapacity() { + final capacity = Jni.env.GetDirectBufferCapacity(reference.pointer); + if (capacity == -1) { + throw StateError( + 'The object is an unaligned view buffer and the processor ' + 'architecture does not support unaligned access.', + ); + } + return capacity; + } + + void _ensureIsDirect() { + if (!isDirect) { + throw StateError( + 'The buffer must be created with `JByteBuffer.allocateDirect`.', + ); + } + } +} + +/// void* memcpy( void* dest, const void* src, std::size_t count ); +@Native(symbol: 'memcpy', isLeaf: true) +external void memcpy(Pointer dest, Pointer src, int count); diff --git a/flutter/microbenchmarks/linux/flutter/generated_plugins.cmake b/flutter/microbenchmarks/linux/flutter/generated_plugins.cmake index 7204441060..7244781b99 100644 --- a/flutter/microbenchmarks/linux/flutter/generated_plugins.cmake +++ b/flutter/microbenchmarks/linux/flutter/generated_plugins.cmake @@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/flutter/microbenchmarks/pubspec.yaml b/flutter/microbenchmarks/pubspec.yaml index 23da62bdfb..80b2bcf0fa 100644 --- a/flutter/microbenchmarks/pubspec.yaml +++ b/flutter/microbenchmarks/pubspec.yaml @@ -17,6 +17,7 @@ dependencies: benchmarking: ^0.6.1 sentry_flutter: path: ../ + jni: ^0.14.0 dev_dependencies: flutter_lints: ^5.0.0 diff --git a/flutter/microbenchmarks/windows/flutter/generated_plugins.cmake b/flutter/microbenchmarks/windows/flutter/generated_plugins.cmake index e3e2f3e784..5af1999cb4 100644 --- a/flutter/microbenchmarks/windows/flutter/generated_plugins.cmake +++ b/flutter/microbenchmarks/windows/flutter/generated_plugins.cmake @@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 53dc8119a7..6f860dc79f 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 8.14.0 +version: 9.0.0-alpha.1 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -7,8 +7,8 @@ issue_tracker: https://github.com/getsentry/sentry-dart/issues documentation: https://docs.sentry.io/platforms/flutter/ environment: - sdk: '>=2.17.0 <4.0.0' - flutter: '>=3.0.0' + sdk: '>=3.5.0 <4.0.0' + flutter: '>=3.24.0' platforms: android: @@ -23,12 +23,13 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 8.14.0 + sentry: 9.0.0-alpha.1 package_info_plus: '>=1.0.0' meta: ^1.3.0 ffi: ^2.0.0 - file: '>=6.1.4' collection: ^1.16.0 + web: ^1.1.0 + jni: 0.14.0 dev_dependencies: build_runner: ^2.4.2 @@ -45,7 +46,9 @@ dev_dependencies: git: url: https://github.com/getsentry/ffigen ref: 6aa2c2642f507eab3df83373189170797a9fa5e7 + jnigen: 0.14.0 + platform: any flutter: plugin: platforms: diff --git a/flutter/scripts/generate-cocoa-bindings.sh b/flutter/scripts/generate-cocoa-bindings.sh index 2dcd488a83..08fc737675 100755 --- a/flutter/scripts/generate-cocoa-bindings.sh +++ b/flutter/scripts/generate-cocoa-bindings.sh @@ -25,7 +25,6 @@ mv "$temp/$subdir" $temp/Sentry.framework binding="lib/src/native/cocoa/binding.dart" dart run ffigen --config ffi-cocoa.yaml -sed -i.bak 's|final class|class|g' $binding sed -i.bak 's|static int startProfilerForTrace_(SentryCocoa _lib, SentryId? traceId)|static int startProfilerForTrace_(SentryCocoa _lib, SentryId1? traceId)|g' $binding rm $binding.bak dart format $binding diff --git a/flutter/scripts/generate-native-bindings.ps1 b/flutter/scripts/generate-native-bindings.ps1 index 67d84de610..445a3434e7 100644 --- a/flutter/scripts/generate-native-bindings.ps1 +++ b/flutter/scripts/generate-native-bindings.ps1 @@ -10,7 +10,6 @@ try $binding = 'lib/src/native/c/binding.dart' dart run ffigen --config ffi-native.yaml $content = Get-Content $binding -Raw - $content = $content -replace 'final class', 'class' $content | Set-Content -NoNewline -Encoding utf8 $binding dart format $binding Get-Item $binding diff --git a/flutter/test/android_platform_exception_event_processor_test.dart b/flutter/test/android_platform_exception_event_processor_test.dart index 25ea8b2c6b..c42505584f 100644 --- a/flutter/test/android_platform_exception_event_processor_test.dart +++ b/flutter/test/android_platform_exception_event_processor_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; // ignore_for_file: invalid_use_of_internal_member import 'package:flutter/services.dart'; diff --git a/flutter/test/event_processor/flutter_enricher_event_processor_test.dart b/flutter/test/event_processor/flutter_enricher_event_processor_test.dart index 6f82a6e6b2..c3555a45ae 100644 --- a/flutter/test/event_processor/flutter_enricher_event_processor_test.dart +++ b/flutter/test/event_processor/flutter_enricher_event_processor_test.dart @@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/event_processor/flutter_enricher_event_processor.dart'; @@ -73,7 +74,6 @@ void main() { final flutterContext = event?.contexts['flutter_context']; expect(flutterContext, isNotNull); expect(flutterContext, isA>()); - expect(flutterContext['renderer'], isNotNull); }); testWidgets('accessibility context', (WidgetTester tester) async { @@ -221,31 +221,43 @@ void main() { }); testWidgets('adds correct flutter runtime', (WidgetTester tester) async { - final checkerMap = { - MockPlatformChecker( - isWebValue: false, - buildMode: MockPlatformCheckerBuildMode.debug): 'Dart VM', - MockPlatformChecker( - isWebValue: false, - buildMode: MockPlatformCheckerBuildMode.profile): 'Dart AOT', - MockPlatformChecker( - isWebValue: false, - buildMode: MockPlatformCheckerBuildMode.release): 'Dart AOT', - MockPlatformChecker( - isWebValue: true, - buildMode: MockPlatformCheckerBuildMode.debug): 'dartdevc', - MockPlatformChecker( - isWebValue: true, - buildMode: MockPlatformCheckerBuildMode.profile): 'dart2js', - MockPlatformChecker( - isWebValue: true, - buildMode: MockPlatformCheckerBuildMode.release): 'dart2js', - }; - - for (var pair in checkerMap.entries) { + final testData = [ + PlatformTestData( + MockPlatform(isWeb: false), + MockRuntimeCheckerBuildMode.debug, + 'Dart VM', + ), + PlatformTestData( + MockPlatform(isWeb: false), + MockRuntimeCheckerBuildMode.profile, + 'Dart AOT', + ), + PlatformTestData( + MockPlatform(isWeb: false), + MockRuntimeCheckerBuildMode.release, + 'Dart AOT', + ), + PlatformTestData( + MockPlatform(isWeb: true), + MockRuntimeCheckerBuildMode.debug, + 'dartdevc', + ), + PlatformTestData( + MockPlatform(isWeb: true), + MockRuntimeCheckerBuildMode.profile, + 'dart2js', + ), + PlatformTestData( + MockPlatform(isWeb: true), + MockRuntimeCheckerBuildMode.release, + 'dart2js', + ), + ]; + + for (var entry in testData) { final enricher = fixture.getSut( binding: () => tester.binding, - checker: pair.key, + platformTestData: entry, ); final event = await enricher.apply(SentryEvent(), Hint()); @@ -253,7 +265,7 @@ void main() { .firstWhere((element) => element.name == 'Flutter'); expect(flutterRuntime?.name, 'Flutter'); - expect(flutterRuntime?.compiler, pair.value); + expect(flutterRuntime?.compiler, entry.compiler); } }); @@ -380,9 +392,9 @@ void main() { testWidgets('$FlutterEnricherEventProcessor gets added on init', (tester) async { - // use a mockplatform checker so that we don't need to mock platform channels - final sentryOptions = - defaultTestOptions(MockPlatformChecker(hasNativeIntegration: false)); + // use a mock platform so that we don't need to mock platform channels + final sentryOptions = defaultTestOptions(); + sentryOptions.platform = MockPlatform.fuchsia(); // Without native loadTestPackage(); await SentryFlutter.init((options) { @@ -416,21 +428,40 @@ void main() { }); } +class PlatformTestData { + PlatformTestData(this.platform, this.buildMode, this.compiler); + MockPlatform platform; + MockRuntimeCheckerBuildMode buildMode; + String compiler; +} + class Fixture { FlutterEnricherEventProcessor getSut({ required WidgetBindingGetter binding, - PlatformChecker? checker, + PlatformTestData? platformTestData, bool hasNativeIntegration = false, bool reportPackages = true, SentryFlutterOptions Function(SentryFlutterOptions)? optionsBuilder, }) { - final platformChecker = checker ?? - MockPlatformChecker( - hasNativeIntegration: hasNativeIntegration, - ); - - final options = defaultTestOptions(platformChecker) + RuntimeChecker runtimeChecker; + if (platformTestData != null) { + runtimeChecker = MockRuntimeChecker( + buildMode: platformTestData.buildMode, + ); + } else { + runtimeChecker = MockRuntimeChecker(); + } + + final options = defaultTestOptions( + platform: + hasNativeIntegration ? MockPlatform.iOS() : MockPlatform.fuchsia(), + checker: runtimeChecker) ..reportPackages = reportPackages; + + if (platformTestData != null) { + options.platform = platformTestData.platform; + } + final customizedOptions = optionsBuilder?.call(options) ?? options; return FlutterEnricherEventProcessor(customizedOptions); } diff --git a/flutter/test/event_processor/screenshot_event_processor_test.dart b/flutter/test/event_processor/screenshot_event_processor_test.dart index 095e398892..e21ba2379f 100644 --- a/flutter/test/event_processor/screenshot_event_processor_test.dart +++ b/flutter/test/event_processor/screenshot_event_processor_test.dart @@ -1,16 +1,17 @@ @Tags(['canvasKit']) // Web renderer where this test can run -library flutter_test; +library; import 'dart:math'; import 'dart:ui'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:sentry_flutter/src/event_processor/screenshot_event_processor.dart'; import 'package:sentry_flutter/src/renderer/renderer.dart'; -import '../mocks.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; +import '../mocks.dart'; import '../replay/replay_test_util.dart'; void main() { @@ -64,7 +65,7 @@ void main() { testWidgets('adds screenshot attachment with masking enabled dart:io', (tester) async { - fixture.options.experimental.privacy.maskAllText = true; + fixture.options.privacy.maskAllText = true; await _addScreenshotAttachment(tester, null, added: true, isWeb: false); }); @@ -134,96 +135,6 @@ void main() { }); }); - group('beforeScreenshot', () { - testWidgets('does add screenshot if beforeScreenshot returns true', - (tester) async { - // ignore: deprecated_member_use_from_same_package - fixture.options.beforeScreenshot = (SentryEvent event, {Hint? hint}) { - return true; - }; - await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, - added: true, isWeb: false); - }); - - testWidgets('does add screenshot if async beforeScreenshot returns true', - (tester) async { - // ignore: deprecated_member_use_from_same_package - fixture.options.beforeScreenshot = - (SentryEvent event, {Hint? hint}) async { - await Future.delayed(Duration(milliseconds: 1)); - return true; - }; - await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, - added: true, isWeb: false); - }); - - testWidgets('does not add screenshot if beforeScreenshot returns false', - (tester) async { - // ignore: deprecated_member_use_from_same_package - fixture.options.beforeScreenshot = (SentryEvent event, {Hint? hint}) { - return false; - }; - await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, - added: false, isWeb: false); - }); - - testWidgets( - 'does not add screenshot if async beforeScreenshot returns false', - (tester) async { - // ignore: deprecated_member_use_from_same_package - fixture.options.beforeScreenshot = - (SentryEvent event, {Hint? hint}) async { - await Future.delayed(Duration(milliseconds: 1)); - return false; - }; - await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, - added: false, isWeb: false); - }); - - testWidgets('does add screenshot if beforeScreenshot throws', - (tester) async { - fixture.options.automatedTestMode = false; - // ignore: deprecated_member_use_from_same_package - fixture.options.beforeScreenshot = (SentryEvent event, {Hint? hint}) { - throw Error(); - }; - await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, - added: true, isWeb: false); - }); - - testWidgets('does add screenshot if async beforeScreenshot throws', - (tester) async { - fixture.options.automatedTestMode = false; - // ignore: deprecated_member_use_from_same_package - fixture.options.beforeScreenshot = - (SentryEvent event, {Hint? hint}) async { - await Future.delayed(Duration(milliseconds: 1)); - throw Error(); - }; - await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, - added: true, isWeb: false); - }); - - testWidgets('passes event & hint to beforeScreenshot callback', - (tester) async { - SentryEvent? beforeScreenshotEvent; - Hint? beforeScreenshotHint; - - // ignore: deprecated_member_use_from_same_package - fixture.options.beforeScreenshot = (SentryEvent event, {Hint? hint}) { - beforeScreenshotEvent = event; - beforeScreenshotHint = hint; - return true; - }; - - await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, - added: true, isWeb: false); - - expect(beforeScreenshotEvent, event); - expect(beforeScreenshotHint, hint); - }); - }); - group('beforeCaptureScreenshot', () { testWidgets('does add screenshot if beforeCapture returns true', (tester) async { @@ -439,7 +350,7 @@ class Fixture { ScreenshotEventProcessor getSut( FlutterRenderer? flutterRenderer, bool isWeb) { options.rendererWrapper = MockRendererWrapper(flutterRenderer); - options.platformChecker = MockPlatformChecker(isWebValue: isWeb); + options.platform = MockPlatform(isWeb: isWeb); return ScreenshotEventProcessor(options); } } diff --git a/flutter/test/event_processor/url_filter/io_filter_event_processor_test.dart b/flutter/test/event_processor/url_filter/io_filter_event_processor_test.dart index 186858888d..a9f6f3617e 100644 --- a/flutter/test/event_processor/url_filter/io_filter_event_processor_test.dart +++ b/flutter/test/event_processor/url_filter/io_filter_event_processor_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; diff --git a/flutter/test/event_processor/url_filter/web_url_filter_event_processor_test.dart b/flutter/test/event_processor/url_filter/web_url_filter_event_processor_test.dart index bc80d45e6b..1fa61d1697 100644 --- a/flutter/test/event_processor/url_filter/web_url_filter_event_processor_test.dart +++ b/flutter/test/event_processor/url_filter/web_url_filter_event_processor_test.dart @@ -1,5 +1,5 @@ @TestOn('browser') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; diff --git a/flutter/test/file_system_transport_test.dart b/flutter/test/file_system_transport_test.dart index 91340f7fb6..0177efb923 100644 --- a/flutter/test/file_system_transport_test.dart +++ b/flutter/test/file_system_transport_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'dart:convert'; diff --git a/flutter/test/frame_tracking/frames_tracking_integration_test.dart b/flutter/test/frame_tracking/frames_tracking_integration_test.dart index f16069f447..b1fff1bb8f 100644 --- a/flutter/test/frame_tracking/frames_tracking_integration_test.dart +++ b/flutter/test/frame_tracking/frames_tracking_integration_test.dart @@ -1,6 +1,6 @@ // ignore_for_file: invalid_use_of_internal_member @TestOn('vm') -library flutter_test; +library; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/flutter/test/initialization_test.dart b/flutter/test/initialization_test.dart index 527b51b247..14b98b051f 100644 --- a/flutter/test/initialization_test.dart +++ b/flutter/test/initialization_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; diff --git a/flutter/test/integrations/debug_print_integration_test.dart b/flutter/test/integrations/debug_print_integration_test.dart index a5580d6352..41827420d7 100644 --- a/flutter/test/integrations/debug_print_integration_test.dart +++ b/flutter/test/integrations/debug_print_integration_test.dart @@ -57,6 +57,7 @@ void main() { test('$DebugPrintIntegration: disabled in debug builds', () { final integration = fixture.getSut(); + integration.call(fixture.hub, fixture.getOptions(debug: true)); debugPrint('Foo Bar'); @@ -94,10 +95,11 @@ class Fixture { bool debug = false, bool enablePrintBreadcrumbs = true, }) { - return defaultTestOptions(MockPlatformChecker( - buildMode: debug - ? MockPlatformCheckerBuildMode.debug - : MockPlatformCheckerBuildMode.release)) + return defaultTestOptions( + checker: MockRuntimeChecker( + buildMode: debug + ? MockRuntimeCheckerBuildMode.debug + : MockRuntimeCheckerBuildMode.release)) ..enablePrintBreadcrumbs = enablePrintBreadcrumbs; } diff --git a/flutter/test/integrations/init_native_sdk_test.dart b/flutter/test/integrations/init_native_sdk_test.dart index 818641073b..02de4fb463 100644 --- a/flutter/test/integrations/init_native_sdk_test.dart +++ b/flutter/test/integrations/init_native_sdk_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -129,10 +129,10 @@ void main() { user: 'admin', pass: '0000', ) - ..experimental.replay.quality = SentryReplayQuality.high - ..experimental.replay.sessionSampleRate = 0.1 - ..experimental.replay.onErrorSampleRate = 0.2 - ..experimental.privacy.mask() + ..replay.quality = SentryReplayQuality.high + ..replay.sessionSampleRate = 0.1 + ..replay.onErrorSampleRate = 0.2 + ..privacy.mask() ..spotlight = Spotlight(enabled: true, url: 'http://localhost:8969/stream'); @@ -217,8 +217,7 @@ MethodChannel createChannelWithCallback( } SentryFlutterOptions createOptions() { - final mockPlatformChecker = MockPlatformChecker(hasNativeIntegration: true); - final options = defaultTestOptions(mockPlatformChecker); + final options = defaultTestOptions(); options.sdk = SdkVersion( name: sdkName, version: sdkVersion, diff --git a/flutter/test/integrations/load_contexts_integration_test.dart b/flutter/test/integrations/load_contexts_integration_test.dart index 33be3e56af..d623c22588 100644 --- a/flutter/test/integrations/load_contexts_integration_test.dart +++ b/flutter/test/integrations/load_contexts_integration_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; @@ -162,7 +162,7 @@ void main() { const expectedId = '1'; String? actualId; - fixture.options.beforeSendTransaction = (transaction) { + fixture.options.beforeSendTransaction = (transaction, hint) { actualIp = transaction.user?.ipAddress; actualId = transaction.user?.id; return transaction; @@ -197,7 +197,7 @@ void main() { const expectedId = '1'; String? actualId; - fixture.options.beforeSendTransaction = (transaction) { + fixture.options.beforeSendTransaction = (transaction, hint) { actualIp = transaction.user?.ipAddress; actualId = transaction.user?.id; return transaction; diff --git a/flutter/test/integrations/load_contexts_integrations_test.dart b/flutter/test/integrations/load_contexts_integrations_test.dart index 7add3f7929..acb7889f7c 100644 --- a/flutter/test/integrations/load_contexts_integrations_test.dart +++ b/flutter/test/integrations/load_contexts_integrations_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; diff --git a/flutter/test/integrations/load_image_list_test.dart b/flutter/test/integrations/load_image_list_test.dart index 95e31a625c..d4c3da3548 100644 --- a/flutter/test/integrations/load_image_list_test.dart +++ b/flutter/test/integrations/load_image_list_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; diff --git a/flutter/test/integrations/native_app_start_handler_test.dart b/flutter/test/integrations/native_app_start_handler_test.dart index b07c0d0726..4ee6c37985 100644 --- a/flutter/test/integrations/native_app_start_handler_test.dart +++ b/flutter/test/integrations/native_app_start_handler_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'package:collection/collection.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index 728eebcc98..c9eeefac1b 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -1,7 +1,6 @@ @TestOn('vm') -library flutter_test; +library; -import 'dart:async'; import 'dart:core'; import 'dart:ui'; @@ -115,47 +114,6 @@ void main() { expect(fixture.frameCallbackHandler.timingsCallback, isNull); }); - - test('with disabled auto app start waits until appStartEnd is set', - () async { - // ignore: deprecated_member_use_from_same_package - fixture.options.autoAppStart = false; - - fixture.callIntegration(); - final timingsCallback = fixture.frameCallbackHandler.timingsCallback!; - timingsCallback([_fakeFrameTiming]); - - expect(fixture.nativeAppStartHandler.calls, 0); - - final appStartEnd = DateTime.fromMicrosecondsSinceEpoch(50); - fixture.sut.appStartEnd = appStartEnd; - - await Future.delayed(Duration(milliseconds: 10)); - - expect(fixture.frameCallbackHandler.timingsCallback, isNull); - expect(fixture.nativeAppStartHandler.calls, 1); - expect(fixture.nativeAppStartHandler.appStartEnd, appStartEnd); - }); - - test('with disabled auto app start waits until timeout', () async { - // ignore: deprecated_member_use_from_same_package - fixture.options.autoAppStart = false; - - fixture.callIntegration(); - final timingsCallback = fixture.frameCallbackHandler.timingsCallback!; - await expectLater( - () => timingsCallback([_fakeFrameTiming]), - throwsA(isA()), - ); - - expect(fixture.nativeAppStartHandler.calls, 0); - - await Future.delayed(Duration(seconds: 11)); - - expect(fixture.frameCallbackHandler.timingsCallback, isNull); - expect(fixture.nativeAppStartHandler.calls, 0); - expect(fixture.nativeAppStartHandler.appStartEnd, null); - }); }); } diff --git a/flutter/test/integrations/native_sdk_integration_test.dart b/flutter/test/integrations/native_sdk_integration_test.dart index 8645a80aa2..7239166b93 100644 --- a/flutter/test/integrations/native_sdk_integration_test.dart +++ b/flutter/test/integrations/native_sdk_integration_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; diff --git a/flutter/test/integrations/web_sdk_integration_test.dart b/flutter/test/integrations/web_sdk_integration_test.dart index 7057adcab3..70a18ea43a 100644 --- a/flutter/test/integrations/web_sdk_integration_test.dart +++ b/flutter/test/integrations/web_sdk_integration_test.dart @@ -1,11 +1,9 @@ @TestOn('browser') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; -import 'package:sentry/src/transport/noop_transport.dart'; import 'package:sentry_flutter/src/integrations/web_sdk_integration.dart'; -import 'package:sentry_flutter/src/web/javascript_transport.dart'; import 'package:sentry_flutter/src/web/script_loader/sentry_script_loader.dart'; import '../mocks.dart'; @@ -27,7 +25,6 @@ void main() { group('enabled', () { setUp(() { - fixture.options.enableSentryJs = true; fixture.options.autoInitializeNativeSdk = true; }); @@ -52,17 +49,9 @@ void main() { _TestScenario( 'with autoInitializeNativeSdk=false', () { - fixture.options.enableSentryJs = true; fixture.options.autoInitializeNativeSdk = false; }, ), - _TestScenario( - 'with enableSentryJs=false', - () { - fixture.options.enableSentryJs = false; - fixture.options.autoInitializeNativeSdk = true; - }, - ), ]; for (final scenario in disabledScenarios) { @@ -84,46 +73,6 @@ void main() { } }); - group('transport configuration', () { - test('integration disabled: does not use javascript transport', () async { - fixture.options.enableSentryJs = false; - fixture.options.autoInitializeNativeSdk = false; - - expect(fixture.options.transport, isA()); - - await sut.call(fixture.hub, fixture.options); - - expect(fixture.options.transport, isA()); - }); - - test( - 'integration enabled and supportsCaptureEnvelope is false: does not use javascript transport', - () async { - fixture.options.enableSentryJs = true; - fixture.options.autoInitializeNativeSdk = true; - when(fixture.web.supportsCaptureEnvelope).thenReturn(false); - - expect(fixture.options.transport, isA()); - - await sut.call(fixture.hub, fixture.options); - - expect(fixture.options.transport, isA()); - }); - - test( - 'integration enabled and supportsCaptureEnvelope is true: uses javascript transport', - () async { - fixture.options.enableSentryJs = true; - fixture.options.autoInitializeNativeSdk = true; - - expect(fixture.options.transport, isA()); - - await sut.call(fixture.hub, fixture.options); - - expect(fixture.options.transport, isA()); - }); - }); - test('closes resources', () async { await sut.close(); diff --git a/flutter/test/mocks.dart b/flutter/test/mocks.dart index 3dce2bbb60..592b70d886 100644 --- a/flutter/test/mocks.dart +++ b/flutter/test/mocks.dart @@ -6,13 +6,13 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:meta/meta.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; -import 'package:sentry/src/platform/platform.dart'; import 'package:sentry/src/sentry_tracer.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/frames_tracking/sentry_delayed_frames_tracker.dart'; import 'package:sentry_flutter/src/native/sentry_native_binding.dart'; import 'package:sentry_flutter/src/renderer/renderer.dart'; import 'package:sentry_flutter/src/web/sentry_js_binding.dart'; +import 'package:sentry/src/platform/platform.dart'; import 'mocks.mocks.dart'; import 'no_such_method_provider.dart'; @@ -20,8 +20,10 @@ import 'no_such_method_provider.dart'; const fakeDsn = 'https://abc@def.ingest.sentry.io/1234567'; const fakeProguardUuid = '3457d982-65ef-576d-a6ad-65b5f30f49a5'; -SentryFlutterOptions defaultTestOptions([PlatformChecker? checker]) { - return SentryFlutterOptions(dsn: fakeDsn, checker: checker) +SentryFlutterOptions defaultTestOptions( + {Platform? platform, RuntimeChecker? checker}) { + return SentryFlutterOptions( + dsn: fakeDsn, platform: platform, checker: checker) ..automatedTestMode = true; } @@ -59,82 +61,29 @@ ISentrySpan startTransactionShim( ]) void main() {} -class MockPlatform with NoSuchMethodProvider implements Platform { - const MockPlatform(this.operatingSystem, - {this.operatingSystemVersion = '', this.localHostname = ''}); - - const MockPlatform.android() : this('android'); - const MockPlatform.iOs() : this('ios'); - const MockPlatform.macOs() : this('macos'); - const MockPlatform.windows() : this('windows'); - const MockPlatform.linux() : this('linux'); - const MockPlatform.fuchsia() : this('fuchsia'); - - @override - final String operatingSystem; - - @override - final String operatingSystemVersion; - - @override - final String localHostname; - - @override - bool get isLinux => (operatingSystem == 'linux'); - - @override - bool get isMacOS => (operatingSystem == 'macos'); - - @override - bool get isWindows => (operatingSystem == 'windows'); - - @override - bool get isAndroid => (operatingSystem == 'android'); - - @override - bool get isIOS => (operatingSystem == 'ios'); - - @override - bool get isFuchsia => (operatingSystem == 'fuchsia'); -} - -class MockPlatformChecker with NoSuchMethodProvider implements PlatformChecker { - MockPlatformChecker({ - this.buildMode = MockPlatformCheckerBuildMode.debug, - this.isWebValue = false, - this.hasNativeIntegration = false, +class MockRuntimeChecker with NoSuchMethodProvider implements RuntimeChecker { + MockRuntimeChecker({ + this.buildMode = MockRuntimeCheckerBuildMode.debug, this.isRoot = true, - Platform? mockPlatform, - }) : _mockPlatform = mockPlatform ?? MockPlatform(''); + }); - final MockPlatformCheckerBuildMode buildMode; - final bool isWebValue; + final MockRuntimeCheckerBuildMode buildMode; final bool isRoot; - final Platform _mockPlatform; - - @override - bool hasNativeIntegration = false; @override - bool isDebugMode() => buildMode == MockPlatformCheckerBuildMode.debug; + bool isDebugMode() => buildMode == MockRuntimeCheckerBuildMode.debug; @override - bool isProfileMode() => buildMode == MockPlatformCheckerBuildMode.profile; + bool isProfileMode() => buildMode == MockRuntimeCheckerBuildMode.profile; @override - bool isReleaseMode() => buildMode == MockPlatformCheckerBuildMode.release; + bool isReleaseMode() => buildMode == MockRuntimeCheckerBuildMode.release; @override bool get isRootZone => isRoot; - - @override - bool get isWeb => isWebValue; - - @override - Platform get platform => _mockPlatform; } -enum MockPlatformCheckerBuildMode { debug, profile, release } +enum MockRuntimeCheckerBuildMode { debug, profile, release } // Does nothing or returns default values. // Useful for when a Hub needs to be passed but is not used. diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index b0114b8905..b0a3f10f34 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -437,11 +437,16 @@ class MockSentryTracer extends _i1.Mock implements _i3.SentryTracer { ) as Map); @override - _i11.Future finish({_i2.SpanStatus? status, DateTime? endTimestamp}) => + _i11.Future finish({ + _i2.SpanStatus? status, + DateTime? endTimestamp, + _i2.Hint? hint, + }) => (super.noSuchMethod( Invocation.method(#finish, [], { #status: status, #endTimestamp: endTimestamp, + #hint: hint, }), returnValue: _i11.Future.value(), returnValueForMissingStub: _i11.Future.value(), @@ -816,11 +821,16 @@ class MockSentrySpan extends _i1.Mock implements _i2.SentrySpan { ) as Map); @override - _i11.Future finish({_i2.SpanStatus? status, DateTime? endTimestamp}) => + _i11.Future finish({ + _i2.SpanStatus? status, + DateTime? endTimestamp, + _i2.Hint? hint, + }) => (super.noSuchMethod( Invocation.method(#finish, [], { #status: status, #endTimestamp: endTimestamp, + #hint: hint, }), returnValue: _i11.Future.value(), returnValueForMissingStub: _i11.Future.value(), @@ -1007,12 +1017,13 @@ class MockSentryClient extends _i1.Mock implements _i2.SentryClient { _i2.SentryTransaction? transaction, { _i2.Scope? scope, _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#scope: scope, #traceContext: traceContext}, + {#scope: scope, #traceContext: traceContext, #hint: hint}, ), returnValue: _i11.Future<_i2.SentryId>.value( _FakeSentryId_5( @@ -1020,7 +1031,7 @@ class MockSentryClient extends _i1.Mock implements _i2.SentryClient { Invocation.method( #captureTransaction, [transaction], - {#scope: scope, #traceContext: traceContext}, + {#scope: scope, #traceContext: traceContext, #hint: hint}, ), ), ), @@ -1033,14 +1044,6 @@ class MockSentryClient extends _i1.Mock implements _i2.SentryClient { returnValue: _i11.Future<_i2.SentryId?>.value(), ) as _i11.Future<_i2.SentryId?>); - @override - _i11.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => - (super.noSuchMethod( - Invocation.method(#captureUserFeedback, [userFeedback]), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); - @override _i11.Future<_i2.SentryId> captureFeedback( _i2.SentryFeedback? feedback, { @@ -2680,14 +2683,6 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), ) as _i11.Future<_i2.SentryId>); - @override - _i11.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => - (super.noSuchMethod( - Invocation.method(#captureUserFeedback, [userFeedback]), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); - @override _i11.Future<_i2.SentryId> captureFeedback( _i2.SentryFeedback? feedback, { @@ -2833,12 +2828,13 @@ class MockHub extends _i1.Mock implements _i2.Hub { _i11.Future<_i2.SentryId> captureTransaction( _i2.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + {#traceContext: traceContext, #hint: hint}, ), returnValue: _i11.Future<_i2.SentryId>.value( _FakeSentryId_5( @@ -2846,7 +2842,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + {#traceContext: traceContext, #hint: hint}, ), ), ), diff --git a/flutter/test/native_memory_test.dart b/flutter/test/native_memory_test.dart index 185590ac69..8590f8a6ac 100644 --- a/flutter/test/native_memory_test.dart +++ b/flutter/test/native_memory_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'dart:typed_data'; diff --git a/flutter/test/native_scope_observer_test.dart b/flutter/test/native_scope_observer_test.dart index e22136bc1b..feb40f5416 100644 --- a/flutter/test/native_scope_observer_test.dart +++ b/flutter/test/native_scope_observer_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; diff --git a/flutter/test/navigation/sentry_display_widget_test.dart b/flutter/test/navigation/sentry_display_widget_test.dart deleted file mode 100644 index 334c75b9b0..0000000000 --- a/flutter/test/navigation/sentry_display_widget_test.dart +++ /dev/null @@ -1,79 +0,0 @@ -// ignore_for_file: invalid_use_of_internal_member - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:sentry/src/sentry_tracer.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; - -import '../fake_frame_callback_handler.dart'; -import '../mocks.dart'; - -void main() { - PageRoute route(RouteSettings? settings) => PageRouteBuilder( - pageBuilder: (_, __, ___) => Container(), - settings: settings, - ); - - late Fixture fixture; - - setUp(() { - fixture = Fixture(); - }); - - testWidgets('SentryDisplayWidget reports manual ttid span after didPush', - (WidgetTester tester) async { - final currentRoute = route(RouteSettings(name: 'Current Route')); - - await tester.runAsync(() async { - fixture.navigatorObserver.didPush(currentRoute, null); - - await tester.pumpWidget(fixture.getSut()); - - await fixture.navigatorObserver.completedDisplayTracking?.future; - }); - - final tracer = fixture.hub.getSpan() as SentryTracer; - final spans = tracer.children.where((element) => - element.context.operation == - SentrySpanOperations.uiTimeToInitialDisplay); - - expect(spans, hasLength(1)); - - final ttidSpan = spans.first; - expect(ttidSpan.context.operation, - SentrySpanOperations.uiTimeToInitialDisplay); - expect(ttidSpan.finished, isTrue); - expect(ttidSpan.context.description, 'Current Route initial display'); - expect(ttidSpan.origin, SentryTraceOrigins.manualUiTimeToDisplay); - final ttidSpanDuration = - ttidSpan.endTimestamp!.difference(ttidSpan.startTimestamp); - - expect(tracer.measurements, hasLength(1)); - final measurement = tracer.measurements['time_to_initial_display']; - expect(measurement, isNotNull); - expect(measurement?.unit, DurationSentryMeasurementUnit.milliSecond); - expect(measurement?.value, ttidSpanDuration.inMilliseconds); - }); -} - -class Fixture { - final Hub hub = Hub(defaultTestOptions()..tracesSampleRate = 1.0); - late final SentryNavigatorObserver navigatorObserver; - final fakeFrameCallbackHandler = FakeFrameCallbackHandler(); - final frameCallbackHandler = FakeFrameCallbackHandler( - postFrameCallbackDelay: Duration(milliseconds: 10)); - - Fixture() { - navigatorObserver = SentryNavigatorObserver(hub: hub); - } - - MaterialApp getSut() { - return MaterialApp( - // ignore: deprecated_member_use_from_same_package - home: SentryDisplayWidget( - frameCallbackHandler: frameCallbackHandler, - child: Text('my text'), - ), - ); - } -} diff --git a/flutter/test/navigation/time_to_display_tracker_test.dart b/flutter/test/navigation/time_to_display_tracker_test.dart index 9a8d820d29..a5fecdcafd 100644 --- a/flutter/test/navigation/time_to_display_tracker_test.dart +++ b/flutter/test/navigation/time_to_display_tracker_test.dart @@ -83,35 +83,6 @@ void main() { await sut.track(transaction, startTimestamp: fixture.startTimestamp); }); }); - - group('with manual strategy', () { - test('finishes ttid span', () async { - final sut = fixture.getSut(); - - Future.delayed(const Duration(milliseconds: 1), () { - fixture.ttidTracker?.markAsManual(); - fixture.ttidTracker?.completeTracking(); - }); - final transaction = fixture.getTransaction() as SentryTracer; - await sut.track(transaction, startTimestamp: fixture.startTimestamp); - - final ttidSpan = _getTTIDSpan(transaction); - expect(ttidSpan, isNotNull); - expect(ttidSpan?.finished, isTrue); - expect(ttidSpan?.origin, SentryTraceOrigins.manualUiTimeToDisplay); - }); - - // skipping test, flaky - test('completes with timeout when not completing the tracking', () async { - final sut = fixture.getSut(); - - fixture.ttidTracker?.markAsManual(); - // Not calling completeTracking() triggers the manual timeout - - final transaction = fixture.getTransaction() as SentryTracer; - await sut.track(transaction, startTimestamp: fixture.startTimestamp); - }, skip: true); - }); }); group('time to full display', () { diff --git a/flutter/test/navigation/time_to_initial_display_tracker_test.dart b/flutter/test/navigation/time_to_initial_display_tracker_test.dart index ebf691da68..1be86954cf 100644 --- a/flutter/test/navigation/time_to_initial_display_tracker_test.dart +++ b/flutter/test/navigation/time_to_initial_display_tracker_test.dart @@ -55,45 +55,8 @@ void main() { .inMilliseconds); }); - test( - 'manual tracking creates and finishes ttid span with correct measurements', - () async { - sut.markAsManual(); - Future.delayed(fixture.finishFrameDuration, () { - sut.completeTracking(); - }); - - final transaction = fixture.getTransaction() as SentryTracer; - await sut.track( - transaction: transaction, - startTimestamp: fixture.startTimestamp, - ); - - final children = transaction.children; - expect(children, hasLength(1)); - - final ttidSpan = children.first; - expect(ttidSpan.context.operation, - SentrySpanOperations.uiTimeToInitialDisplay); - expect(ttidSpan.finished, isTrue); - expect(ttidSpan.context.description, 'Regular route initial display'); - expect(ttidSpan.origin, SentryTraceOrigins.manualUiTimeToDisplay); - final ttidMeasurement = - transaction.measurements['time_to_initial_display']; - expect(ttidMeasurement, isNotNull); - expect(ttidMeasurement?.unit, DurationSentryMeasurementUnit.milliSecond); - expect(ttidMeasurement?.value, - greaterThanOrEqualTo(fixture.finishFrameDuration.inMilliseconds)); - expect( - ttidMeasurement?.value, - ttidSpan.endTimestamp! - .difference(ttidSpan.startTimestamp) - .inMilliseconds); - }); - test('starting after completing still finished correctly', () async { await Future.delayed(fixture.finishFrameDuration, () { - sut.markAsManual(); sut.completeTracking(); }); @@ -111,7 +74,7 @@ void main() { SentrySpanOperations.uiTimeToInitialDisplay); expect(ttidSpan.finished, isTrue); expect(ttidSpan.context.description, 'Regular route initial display'); - expect(ttidSpan.origin, SentryTraceOrigins.manualUiTimeToDisplay); + expect(ttidSpan.origin, SentryTraceOrigins.autoUiTimeToDisplay); final ttidMeasurement = transaction.measurements['time_to_initial_display']; expect(ttidMeasurement, isNotNull); @@ -173,50 +136,18 @@ void main() { expect(futureEndTime, null); }); - test('can complete as null in manual mode with timeout', () async { - final sut = fixture.getSut(); - sut.markAsManual(); - // Not calling completeTracking() triggers the manual timeout - - final futureEndTime = await sut.determineEndTime(); - - expect(futureEndTime, null); - }); - test('can complete automatically in approximation mode', () async { final futureEndTime = await sut.determineEndTime(); expect(futureEndTime, isNotNull); }); - test('can complete manually in manual mode', () async { - sut.markAsManual(); - Future.delayed(Duration(milliseconds: 1), () { - sut.completeTracking(); - }); - final futureEndTime = await sut.determineEndTime(); - - expect(futureEndTime, isNotNull); - }); - test('returns the correct approximation end time', () async { final endTme = await sut.determineEndTime(); expect(endTme?.difference(fixture.startTimestamp).inSeconds, fixture.finishFrameDuration.inSeconds); }); - - test('returns the correct manual end time', () async { - sut.markAsManual(); - Future.delayed(fixture.finishFrameDuration, () { - sut.completeTracking(); - }); - - final endTime = await sut.determineEndTime(); - - expect(endTime?.difference(fixture.startTimestamp).inSeconds, - fixture.finishFrameDuration.inSeconds); - }); }); } diff --git a/flutter/test/profiling_test.dart b/flutter/test/profiling_test.dart index 510daac9f0..1091f893f1 100644 --- a/flutter/test/profiling_test.dart +++ b/flutter/test/profiling_test.dart @@ -1,13 +1,13 @@ @TestOn('vm') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/profiling.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'mocks.dart'; import 'mocks.mocks.dart'; -import 'sentry_flutter_test.dart'; void main() { late MockSentryNativeBinding mock; @@ -20,7 +20,7 @@ void main() { group('$SentryNativeProfilerFactory', () { Hub hubWithSampleRate(double profilesSampleRate) { final o = defaultTestOptions(); - o.platformChecker = getPlatformChecker(platform: MockPlatform.iOs()); + o.platform = MockPlatform.iOS(); o.profilesSampleRate = profilesSampleRate; final hub = MockHub(); diff --git a/flutter/test/replay/android_replay_recorder_web.dart b/flutter/test/replay/android_replay_recorder_web.dart new file mode 100644 index 0000000000..ab8bc199bb --- /dev/null +++ b/flutter/test/replay/android_replay_recorder_web.dart @@ -0,0 +1,21 @@ +// ignore_for_file: invalid_use_of_internal_member + +import 'dart:async'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/replay/scheduled_recorder.dart'; +import 'package:sentry_flutter/src/replay/scheduled_recorder_config.dart'; + +class AndroidReplayRecorder extends ScheduledScreenshotRecorder { + static AndroidReplayRecorder Function( + ScheduledScreenshotRecorderConfig, SentryFlutterOptions) factory = + AndroidReplayRecorder.new; + + AndroidReplayRecorder(super.config, super.options); + + @override + Future start() async { + super.start(); + } +} diff --git a/flutter/test/replay/replay_integration_test.dart b/flutter/test/replay/replay_integration_test.dart index e8a0bc8a27..9d029083a1 100644 --- a/flutter/test/replay/replay_integration_test.dart +++ b/flutter/test/replay/replay_integration_test.dart @@ -1,7 +1,7 @@ // ignore_for_file: invalid_use_of_internal_member @TestOn('vm') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; @@ -37,7 +37,7 @@ void main() { '$ReplayIntegration in options.sdk.integrations when supportsReplay=$supportsReplay', () { when(native.supportsReplay).thenReturn(supportsReplay); - options.experimental.replay.sessionSampleRate = 1.0; + options.replay.sessionSampleRate = 1.0; sut.call(hub, options); var matcher = contains(replayIntegrationName); matcher = supportsReplay ? matcher : isNot(matcher); @@ -49,7 +49,7 @@ void main() { test( '$ReplayIntegration in options.sdk.integrations when sessionSampleRate=$sampleRate', () { - options.experimental.replay.sessionSampleRate = sampleRate; + options.replay.sessionSampleRate = sampleRate; sut.call(hub, options); var matcher = contains(replayIntegrationName); matcher = sampleRate > 0 ? matcher : isNot(matcher); @@ -61,7 +61,7 @@ void main() { test( '$ReplayEventProcessor in options.EventProcessors when onErrorSampleRate=$sampleRate', () async { - options.experimental.replay.onErrorSampleRate = sampleRate; + options.replay.onErrorSampleRate = sampleRate; await sut.call(hub, options); if (sampleRate > 0) { @@ -74,7 +74,7 @@ void main() { } testWidgets('Configures replay when displayed', (tester) async { - options.experimental.replay.sessionSampleRate = 1.0; + options.replay.sessionSampleRate = 1.0; when(native.setReplayConfig(any)).thenReturn(null); sut.call(hub, options); @@ -90,8 +90,8 @@ void main() { }); testWidgets('Adjusts resolution based on quality', (tester) async { - options.experimental.replay.sessionSampleRate = 1.0; - options.experimental.replay.quality = SentryReplayQuality.low; + options.replay.sessionSampleRate = 1.0; + options.replay.quality = SentryReplayQuality.low; when(native.setReplayConfig(any)).thenReturn(null); sut.call(hub, options); diff --git a/flutter/test/replay/replay_native_test.dart b/flutter/test/replay/replay_native_test.dart index 90bfcbc2c1..b57e767d87 100644 --- a/flutter/test/replay/replay_native_test.dart +++ b/flutter/test/replay/replay_native_test.dart @@ -1,16 +1,20 @@ // ignore_for_file: invalid_use_of_internal_member @TestOn('vm') -library flutter_test; +library; import 'dart:async'; -import 'package:file/file.dart'; -import 'package:file/memory.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/native/factory.dart'; +import 'android_replay_recorder_web.dart' // see https://github.com/flutter/flutter/issues/160675 + if (dart.library.io) 'package:sentry_flutter/src/native/java/android_replay_recorder.dart'; +import 'package:sentry_flutter/src/replay/scheduled_recorder.dart'; +import 'package:sentry_flutter/src/screenshot/screenshot.dart'; import '../native_memory_web_mock.dart' if (dart.library.io) 'package:sentry_flutter/src/native/native_memory.dart'; import 'package:sentry_flutter/src/native/sentry_native_binding.dart'; @@ -25,21 +29,27 @@ void main() { for (final mockPlatform in [ MockPlatform.android(), - MockPlatform.iOs(), + MockPlatform.iOS(), ]) { group('$SentryNativeBinding (${mockPlatform.operatingSystem})', () { late SentryNativeBinding sut; late NativeChannelFixture native; late SentryFlutterOptions options; late MockHub hub; - late FileSystem fs; late Map replayConfig; + late _MockAndroidReplayRecorder mockAndroidRecorder; setUp(() { hub = MockHub(); - fs = MemoryFileSystem.test(); native = NativeChannelFixture(); + options = defaultTestOptions() + ..platform = mockPlatform + ..methodChannel = native.channel + ..replay.quality = SentryReplayQuality.low; + + sut = createBinding(options); + if (mockPlatform.isIOS) { replayConfig = { 'replayId': '123', @@ -47,23 +57,15 @@ void main() { } else if (mockPlatform.isAndroid) { replayConfig = { 'replayId': '123', - 'directory': 'dir', 'width': 800, 'height': 600, 'frameRate': 1000, }; - fs.directory(replayConfig['directory']).createSync(recursive: true); - when(native.handler('addReplayScreenshot', any)) - .thenAnswer((_) => Future.value()); + AndroidReplayRecorder.factory = (config, options) { + mockAndroidRecorder = _MockAndroidReplayRecorder(config, options); + return mockAndroidRecorder; + }; } - - options = - defaultTestOptions(MockPlatformChecker(mockPlatform: mockPlatform)) - ..fileSystem = fs - ..methodChannel = native.channel - ..experimental.replay.quality = SentryReplayQuality.low; - - sut = createBinding(options); }); tearDown(() async { @@ -72,8 +74,8 @@ void main() { group('replay recorder', () { setUp(() async { - options.experimental.replay.sessionSampleRate = 0.1; - options.experimental.replay.onErrorSampleRate = 0.1; + options.replay.sessionSampleRate = 0.1; + options.replay.onErrorSampleRate = 0.1; await sut.init(hub); }); @@ -103,6 +105,11 @@ void main() { if (mockPlatform.isAndroid) { await native.invokeFromNative('ReplayRecorder.stop'); + AndroidReplayRecorder.factory = AndroidReplayRecorder.new; + + // Workaround for "A Timer is still pending even after the widget tree was disposed." + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); } }); }); @@ -131,79 +138,40 @@ void main() { await pumpTestElement(tester); if (mockPlatform.isAndroid) { - final replayDir = fs.directory(replayConfig['directory']); - - var callbackFinished = Completer(); - nextFrame({bool wait = true}) async { - final future = callbackFinished.future; + final future = mockAndroidRecorder.completer.future; await tester.pumpAndWaitUntil(future, requiredToComplete: wait); } - imageSizeBytes(File file) => file.readAsBytesSync().length; - - final capturedImages = {}; - when(native.handler('addReplayScreenshot', any)) - .thenAnswer((invocation) { - final path = - invocation.positionalArguments[1]["path"] as String; - capturedImages[path] = imageSizeBytes(fs.file(path)); - callbackFinished.complete(); - callbackFinished = Completer(); - return null; - }); - - fsImages() { - final files = replayDir.listSync().map((f) => f as File); - return {for (var f in files) f.path: imageSizeBytes(f)}; - } - - await nextFrame(wait: false); - expect(fsImages(), isEmpty); - verifyNever(native.handler('addReplayScreenshot', any)); - await native.invokeFromNative( 'ReplayRecorder.start', replayConfig); await nextFrame(); - expect(fsImages().values, isNotEmpty); - final size = fsImages().values.first; - expect(size, greaterThan(3000)); - expect(fsImages().values, [size]); - expect(capturedImages, equals(fsImages())); - - await nextFrame(); - fsImages().values.forEach((s) => expect(s, size)); - expect(capturedImages, equals(fsImages())); + expect(mockAndroidRecorder.captured, isNotEmpty); + final screenshot = mockAndroidRecorder.captured.first; + expect(screenshot.width, replayConfig['width']); + expect(screenshot.height, replayConfig['height']); await native.invokeFromNative('ReplayRecorder.pause'); - var count = capturedImages.length; + var count = mockAndroidRecorder.captured.length; await nextFrame(wait: false); await Future.delayed(const Duration(milliseconds: 100)); - fsImages().values.forEach((s) => expect(s, size)); - expect(capturedImages, equals(fsImages())); - expect(capturedImages.length, count); + expect(mockAndroidRecorder.captured.length, equals(count)); await nextFrame(wait: false); - fsImages().values.forEach((s) => expect(s, size)); - expect(capturedImages, equals(fsImages())); - expect(capturedImages.length, count); + expect(mockAndroidRecorder.captured.length, equals(count)); await native.invokeFromNative('ReplayRecorder.resume'); await nextFrame(); - fsImages().values.forEach((s) => expect(s, size)); - expect(capturedImages, equals(fsImages())); - expect(capturedImages.length, greaterThan(count)); + expect(mockAndroidRecorder.captured.length, greaterThan(count)); await native.invokeFromNative('ReplayRecorder.stop'); - count = capturedImages.length; + count = mockAndroidRecorder.captured.length; await Future.delayed(const Duration(milliseconds: 100)); await nextFrame(wait: false); - fsImages().values.forEach((s) => expect(s, size)); - expect(capturedImages, equals(fsImages())); - expect(capturedImages.length, count); + expect(mockAndroidRecorder.captured.length, equals(count)); } else if (mockPlatform.isIOS) { Future captureAndVerify() async { final future = native.invokeFromNative( @@ -233,3 +201,22 @@ void main() { }); } } + +class _MockAndroidReplayRecorder extends ScheduledScreenshotRecorder + implements AndroidReplayRecorder { + final captured = []; + var completer = Completer(); + + _MockAndroidReplayRecorder(super.config, super.options) { + super.callback = (screenshot, _) async { + captured.add(screenshot); + completer.complete(); + completer = Completer(); + }; + } + + @override + Future start() async { + super.start(); + } +} diff --git a/flutter/test/replay/scheduled_recorder_test.dart b/flutter/test/replay/scheduled_recorder_test.dart index add5c67278..f2e672a208 100644 --- a/flutter/test/replay/scheduled_recorder_test.dart +++ b/flutter/test/replay/scheduled_recorder_test.dart @@ -1,7 +1,7 @@ // For some reason, this test is not working in the browser but that's OK, we // don't support video recording anyway. @TestOn('vm') -library dart_test; +library; import 'dart:async'; diff --git a/flutter/test/screenshot/masking_config_test.dart b/flutter/test/screenshot/masking_config_test.dart index a8bdf9d9a4..639688ce2b 100644 --- a/flutter/test/screenshot/masking_config_test.dart +++ b/flutter/test/screenshot/masking_config_test.dart @@ -148,7 +148,7 @@ void main() async { group('$SentryReplayOptions.buildMaskingConfig()', () { List rulesAsStrings(SentryPrivacyOptions options) { final config = - options.buildMaskingConfig(MockLogger().call, PlatformChecker()); + options.buildMaskingConfig(MockLogger().call, RuntimeChecker()); return config.rules .map((rule) => rule.toString()) // These normalize the string on VM & js & wasm: diff --git a/flutter/test/screenshot/recorder_test.dart b/flutter/test/screenshot/recorder_test.dart index 85ff006748..b89869cd6f 100644 --- a/flutter/test/screenshot/recorder_test.dart +++ b/flutter/test/screenshot/recorder_test.dart @@ -1,7 +1,7 @@ // For some reason, this test is not working in the browser but that's OK, we // don't support video recording anyway. @TestOn('vm') -library dart_test; +library; import 'dart:typed_data'; import 'dart:ui'; @@ -9,7 +9,6 @@ import 'dart:ui'; import 'package:flutter/widgets.dart' as widgets; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:sentry_flutter/src/replay/replay_recorder.dart'; import 'package:sentry_flutter/src/screenshot/recorder.dart'; import 'package:sentry_flutter/src/screenshot/recorder_config.dart'; import 'package:sentry_flutter/src/screenshot/screenshot.dart'; @@ -93,7 +92,7 @@ void main() async { final fixture = await _Fixture.create(tester); fixture.options ..automatedTestMode = true - ..experimental.privacy.maskCallback((el, widget) { + ..privacy.maskCallback((el, widget) { throw Exception('testing masking error'); }); @@ -107,38 +106,13 @@ void main() async { final fixture = await _Fixture.create(tester); fixture.options ..automatedTestMode = false - ..experimental.privacy.maskCallback((el, widget) { + ..privacy.maskCallback((el, widget) { throw Exception('testing masking error'); }); expect(await fixture.capture(), isNull); }); - // TODO: remove in the next major release, see _SentryFlutterExperimentalOptions. - group('Widget filter is used based on config or application', () { - test('Uses widget filter by default for Replay', () { - final sut = ReplayScreenshotRecorder( - ScreenshotRecorderConfig(), - defaultTestOptions(), - ); - expect(sut.hasWidgetFilter, isTrue); - }); - - test('Does not use widget filter by default for Screenshots', () { - final sut = - ScreenshotRecorder(ScreenshotRecorderConfig(), defaultTestOptions()); - expect(sut.hasWidgetFilter, isFalse); - }); - - test( - 'Uses widget filter for Screenshots when privacy configured explicitly', - () { - final sut = ScreenshotRecorder(ScreenshotRecorderConfig(), - defaultTestOptions()..experimental.privacy.maskAllText = false); - expect(sut.hasWidgetFilter, isTrue); - }); - }); - group('$Screenshot', () { test('listEquals()', () { expect( diff --git a/flutter/test/screenshot/sentry_screenshot_widget_test.dart b/flutter/test/screenshot/sentry_screenshot_widget_test.dart index 3e04e2fde2..2bf312b790 100644 --- a/flutter/test/screenshot/sentry_screenshot_widget_test.dart +++ b/flutter/test/screenshot/sentry_screenshot_widget_test.dart @@ -1,5 +1,6 @@ @TestOn('vm') -library flutter_test; +library; +// ignore_for_file: invalid_use_of_internal_member import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; diff --git a/flutter/test/screenshot/widget_filter_test.dart b/flutter/test/screenshot/widget_filter_test.dart index 01b22f9a13..c626252f22 100644 --- a/flutter/test/screenshot/widget_filter_test.dart +++ b/flutter/test/screenshot/widget_filter_test.dart @@ -24,13 +24,13 @@ void main() async { final createSut = ( {bool redactImages = false, bool redactText = false, - PlatformChecker? platformChecker}) { + RuntimeChecker? runtimeChecker}) { final privacyOptions = SentryPrivacyOptions() ..maskAllImages = redactImages ..maskAllText = redactText; logger.clear(); final maskingConfig = privacyOptions.buildMaskingConfig( - logger.call, platformChecker ?? PlatformChecker()); + logger.call, runtimeChecker ?? RuntimeChecker()); return WidgetFilter(maskingConfig, logger.call); }; @@ -219,12 +219,12 @@ void main() async { }); group('warning on sensitive widgets', () { - assert(MockPlatformCheckerBuildMode.values.length == 3); - for (final buildMode in MockPlatformCheckerBuildMode.values) { + assert(MockRuntimeCheckerBuildMode.values.length == 3); + for (final buildMode in MockRuntimeCheckerBuildMode.values) { testWidgets(buildMode.name, (tester) async { final sut = createSut( redactText: true, - platformChecker: MockPlatformChecker(buildMode: buildMode)); + runtimeChecker: MockRuntimeChecker(buildMode: buildMode)); final element = await pumpTestElement(tester, children: [CustomPasswordWidget()]); sut.obscure( @@ -236,7 +236,7 @@ void main() async { .map((item) => item.message) .toList(); - if (buildMode == MockPlatformCheckerBuildMode.debug) { + if (buildMode == MockRuntimeCheckerBuildMode.debug) { expect( logMessages, anyElement(contains( diff --git a/flutter/test/sentry_flutter_options_test.dart b/flutter/test/sentry_flutter_options_test.dart index 7c4d2e79b1..81f723a061 100644 --- a/flutter/test/sentry_flutter_options_test.dart +++ b/flutter/test/sentry_flutter_options_test.dart @@ -1,13 +1,12 @@ import 'package:flutter_test/flutter_test.dart'; - +import 'package:sentry/src/platform/mock_platform.dart'; import 'mocks.dart'; void main() { group('SentryFlutterOptions', () { testWidgets('auto breadcrumb tracking: has native integration', (WidgetTester tester) async { - final options = - defaultTestOptions(MockPlatformChecker(hasNativeIntegration: true)); + final options = defaultTestOptions(); expect(options.enableAppLifecycleBreadcrumbs, isFalse); expect(options.enableWindowMetricBreadcrumbs, isFalse); @@ -19,8 +18,7 @@ void main() { testWidgets('auto breadcrumb tracking: without native integration', (WidgetTester tester) async { - final options = - defaultTestOptions(MockPlatformChecker(hasNativeIntegration: false)); + final options = defaultTestOptions(platform: MockPlatform.fuchsia()); expect(options.enableAppLifecycleBreadcrumbs, isTrue); expect(options.enableWindowMetricBreadcrumbs, isTrue); diff --git a/flutter/test/sentry_flutter_test.dart b/flutter/test/sentry_flutter_test.dart index d6fd3d97b4..52aa973654 100644 --- a/flutter/test/sentry_flutter_test.dart +++ b/flutter/test/sentry_flutter_test.dart @@ -1,11 +1,10 @@ // ignore_for_file: invalid_use_of_internal_member -import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'package:sentry/src/dart_exception_type_identifier.dart'; -import 'package:sentry/src/platform/platform.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/file_system_transport.dart'; import 'package:sentry_flutter/src/flutter_exception_type_identifier.dart'; @@ -17,6 +16,7 @@ import 'package:sentry_flutter/src/renderer/renderer.dart'; import 'package:sentry_flutter/src/replay/integration.dart'; import 'package:sentry_flutter/src/version.dart'; import 'package:sentry_flutter/src/view_hierarchy/view_hierarchy_integration.dart'; +import 'package:sentry_flutter/src/web/javascript_transport.dart'; import 'mocks.dart'; import 'mocks.mocks.dart'; @@ -72,9 +72,10 @@ void main() { late final SentryFlutterOptions options; late final Transport transport; - final sentryFlutterOptions = defaultTestOptions( - getPlatformChecker(platform: MockPlatform.android())) - ..methodChannel = native.channel; + final sentryFlutterOptions = + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.android() + ..methodChannel = native.channel; await SentryFlutter.init( (o) async { @@ -130,7 +131,8 @@ void main() { late final Transport transport; final sentryFlutterOptions = - defaultTestOptions(getPlatformChecker(platform: MockPlatform.iOs())) + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.iOS() ..methodChannel = native.channel; await SentryFlutter.init( @@ -184,7 +186,8 @@ void main() { List integrations = []; Transport transport = MockTransport(); final sentryFlutterOptions = - defaultTestOptions(getPlatformChecker(platform: MockPlatform.macOs())) + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.macOS() ..methodChannel = native.channel; await SentryFlutter.init( @@ -227,10 +230,11 @@ void main() { test('Windows', () async { List integrations = []; Transport transport = MockTransport(); - final sentryFlutterOptions = defaultTestOptions( - getPlatformChecker(platform: MockPlatform.windows())) - // We need to disable native init because sentry.dll is not available here. - ..autoInitializeNativeSdk = false; + final sentryFlutterOptions = + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.windows() + // We need to disable native init because sentry.dll is not available here. + ..autoInitializeNativeSdk = false; await SentryFlutter.init( (options) async { @@ -274,7 +278,8 @@ void main() { List integrations = []; Transport transport = MockTransport(); final sentryFlutterOptions = - defaultTestOptions(getPlatformChecker(platform: MockPlatform.linux())) + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.linux() ..methodChannel = native.channel // We need to disable native init because libsentry.so is not available here. ..autoInitializeNativeSdk = false; @@ -323,7 +328,8 @@ void main() { List integrations = []; Transport transport = MockTransport(); final sentryFlutterOptions = - defaultTestOptions(getPlatformChecker(platform: MockPlatform.linux())) + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.linux(isWeb: true) ..methodChannel = native.channel; await SentryFlutter.init( @@ -336,7 +342,7 @@ void main() { options: sentryFlutterOptions, ); - expect(transport, isNot(isA())); + expect(transport, isA()); testScopeObserver( options: sentryFlutterOptions, @@ -368,8 +374,9 @@ void main() { }, testOn: 'browser'); test('Web (custom zone)', () async { - final sentryFlutterOptions = defaultTestOptions( - getPlatformChecker(platform: MockPlatform.linux(), isRootZone: false)) + final checker = MockRuntimeChecker(isRoot: false); + final sentryFlutterOptions = defaultTestOptions(checker: checker) + ..platform = MockPlatform.android(isWeb: true) ..methodChannel = native.channel; await SentryFlutter.init( @@ -395,7 +402,8 @@ void main() { List integrations = []; Transport transport = MockTransport(); final sentryFlutterOptions = - defaultTestOptions(getPlatformChecker(platform: MockPlatform.iOs())) + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.iOS(isWeb: true) ..methodChannel = native.channel; // Tests that iOS || macOS integrations aren't added on a browser which @@ -409,7 +417,7 @@ void main() { options: sentryFlutterOptions, ); - expect(transport, isNot(isA())); + expect(transport, isA()); testConfiguration( integrations: integrations, @@ -438,7 +446,8 @@ void main() { List integrations = []; Transport transport = MockTransport(); final sentryFlutterOptions = - defaultTestOptions(getPlatformChecker(platform: MockPlatform.macOs())) + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.macOS(isWeb: true) ..methodChannel = native.channel; // Tests that iOS || macOS integrations aren't added on a browser which @@ -452,7 +461,7 @@ void main() { options: sentryFlutterOptions, ); - expect(transport, isNot(isA())); + expect(transport, isA()); testConfiguration( integrations: integrations, @@ -481,9 +490,10 @@ void main() { test('Web && Android', () async { List integrations = []; Transport transport = MockTransport(); - final sentryFlutterOptions = defaultTestOptions( - getPlatformChecker(platform: MockPlatform.android())) - ..methodChannel = native.channel; + final sentryFlutterOptions = + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.android(isWeb: true) + ..methodChannel = native.channel; // Tests that Android integrations aren't added on an Android browser await SentryFlutter.init( @@ -495,7 +505,7 @@ void main() { options: sentryFlutterOptions, ); - expect(transport, isNot(isA())); + expect(transport, isA()); testConfiguration( integrations: integrations, @@ -530,7 +540,8 @@ void main() { List integrations = []; final sentryFlutterOptions = - defaultTestOptions(getPlatformChecker(platform: MockPlatform.iOs())) + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.iOS() ..methodChannel = native.channel ..rendererWrapper = MockRendererWrapper(FlutterRenderer.skia) ..release = '' @@ -557,7 +568,8 @@ void main() { List integrations = []; final sentryFlutterOptions = - defaultTestOptions(getPlatformChecker(platform: MockPlatform.iOs())) + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.iOS() ..rendererWrapper = MockRendererWrapper(FlutterRenderer.canvasKit) ..release = '' ..dist = ''; @@ -583,7 +595,8 @@ void main() { List integrations = []; final sentryFlutterOptions = - defaultTestOptions(getPlatformChecker(platform: MockPlatform.iOs())) + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.iOS(isWeb: true) ..rendererWrapper = MockRendererWrapper(FlutterRenderer.html) ..release = '' ..dist = ''; @@ -616,9 +629,10 @@ void main() { }); test('test that initial values are set correctly', () async { - final sentryFlutterOptions = defaultTestOptions( - getPlatformChecker(platform: MockPlatform.android())) - ..methodChannel = native.channel; + final sentryFlutterOptions = + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.android() + ..methodChannel = native.channel; await SentryFlutter.init( (options) { @@ -637,9 +651,10 @@ void main() { test( 'enablePureDartSymbolication is set to false during SentryFlutter init', () async { - final sentryFlutterOptions = defaultTestOptions( - getPlatformChecker(platform: MockPlatform.android())) - ..methodChannel = native.channel; + final sentryFlutterOptions = + defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.android() + ..methodChannel = native.channel; SentryFlutter.native = mockNativeBinding(); await SentryFlutter.init( @@ -702,8 +717,8 @@ void main() { test( 'should add DartExceptionTypeIdentifier and FlutterExceptionTypeIdentifier by default', () async { - final actualOptions = defaultTestOptions( - getPlatformChecker(platform: MockPlatform.android())) + final actualOptions = defaultTestOptions(checker: MockRuntimeChecker()) + ..platform = MockPlatform.android() ..methodChannel = native.channel; await SentryFlutter.init( @@ -757,16 +772,3 @@ void loadTestPackage() { installerStore: null, ); } - -PlatformChecker getPlatformChecker({ - required Platform platform, - bool isWeb = kIsWeb, - bool isRootZone = true, -}) { - final platformChecker = PlatformChecker( - platform: platform, - isWeb: isWeb, - isRootZone: isRootZone, - ); - return platformChecker; -} diff --git a/flutter/test/sentry_native/sentry_native_test.dart b/flutter/test/sentry_native/sentry_native_test.dart index 5f168a919d..9817bfb71a 100644 --- a/flutter/test/sentry_native/sentry_native_test.dart +++ b/flutter/test/sentry_native/sentry_native_test.dart @@ -2,7 +2,7 @@ // a browser. @TestOn('vm') doesn't help by itself in this case because imports // are still evaluated, thus causing a compilation failure. @TestOn('vm && (windows || linux)') -library sentry_native_test; +library; import 'package:flutter_test/flutter_test.dart'; diff --git a/flutter/test/sentry_native/sentry_native_test_ffi.dart b/flutter/test/sentry_native/sentry_native_test_ffi.dart index 0cdd67ca5f..20f4df42ee 100644 --- a/flutter/test/sentry_native/sentry_native_test_ffi.dart +++ b/flutter/test/sentry_native/sentry_native_test_ffi.dart @@ -23,6 +23,8 @@ extension on NativeBackend { // NOTE: Don't run/debug this main(), it likely won't work. // You can use main() in `sentry_native_test.dart`. void main() { + final currentPlatform = platform.Platform(); + final repoRootDir = Directory.current.path.endsWith('/test') ? Directory.current.parent.path : Directory.current.path; @@ -34,12 +36,12 @@ void main() { setUpAll(() async { late final List expectedDistFiles; if (backend.actualValue == NativeBackend.crashpad) { - expectedDistFiles = platform.instance.isWindows + expectedDistFiles = currentPlatform.isWindows ? ['sentry.dll', 'crashpad_handler.exe', 'crashpad_wer.dll'] : ['libsentry.so', 'crashpad_handler']; } else { expectedDistFiles = - platform.instance.isWindows ? ['sentry.dll'] : ['libsentry.so']; + currentPlatform.isWindows ? ['sentry.dll'] : ['libsentry.so']; } helper = NativeTestHelper( @@ -246,10 +248,10 @@ void main() { test('loadDebugImages', () async { final list = await sut.loadDebugImages(SentryStackTrace(frames: [])); expect(list, isNotEmpty); - expect(list![0].type, platform.instance.isWindows ? 'pe' : 'elf'); + expect(list![0].type, currentPlatform.isWindows ? 'pe' : 'elf'); expect(list[0].debugId!.length, greaterThan(30)); - expect(list[0].debugFile, - platform.instance.isWindows ? isNotEmpty : isNull); + expect( + list[0].debugFile, currentPlatform.isWindows ? isNotEmpty : isNull); expect(list[0].imageSize, greaterThan(0)); expect(list[0].imageAddr, startsWith('0x')); expect(list[0].imageAddr?.length, greaterThan(2)); @@ -305,6 +307,7 @@ class NativeTestHelper { /// Compile sentry-native using CMake, as if it was part of a Flutter app. /// Returns the directory containing built libraries Future _buildSentryNative() async { + final currentPlatform = platform.Platform(); if (!_builtVersionIsExpected()) { Directory(cmakeConfDir).createSync(recursive: true); Directory(buildOutputDir).createSync(recursive: true); @@ -314,7 +317,7 @@ int main(int argc, char *argv[]) { return 0; } File('$cmakeConfDir/CMakeLists.txt').writeAsStringSync(''' cmake_minimum_required(VERSION 3.14) project(sentry-native-flutter-test) -add_subdirectory(../../../${platform.instance.operatingSystem} plugin) +add_subdirectory(../../../${currentPlatform.operatingSystem.name} plugin) add_executable(\${CMAKE_PROJECT_NAME} main.c) target_link_libraries(\${CMAKE_PROJECT_NAME} PRIVATE sentry_flutter_plugin) @@ -333,7 +336,7 @@ set(CMAKE_INSTALL_PREFIX "${buildOutputDir.replaceAll('\\', '/')}") '--config', 'Release', ]); - if (platform.instance.isLinux && + if (currentPlatform.isLinux && nativeBackend.actualValue == NativeBackend.crashpad) { await _exec('chmod', ['+x', '$buildOutputDir/crashpad_handler']); } diff --git a/flutter/test/sentry_native_channel_test.dart b/flutter/test/sentry_native_channel_test.dart index 8e6983758b..37ac30cd3e 100644 --- a/flutter/test/sentry_native_channel_test.dart +++ b/flutter/test/sentry_native_channel_test.dart @@ -1,27 +1,27 @@ // ignore_for_file: inference_failure_on_function_invocation @TestOn('vm') -library flutter_test; +library; import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; +import 'package:sentry/src/platform/platform.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/native/factory.dart'; import 'package:sentry_flutter/src/native/method_channel_helper.dart'; import 'package:sentry_flutter/src/native/sentry_native_binding.dart'; -import 'package:sentry/src/platform/platform.dart' as platform; import 'package:sentry_flutter/src/replay/replay_config.dart'; +import 'package:sentry/src/platform/mock_platform.dart'; import 'mocks.dart'; import 'mocks.mocks.dart'; -import 'sentry_flutter_test.dart'; void main() { for (var mockPlatform in [ MockPlatform.android(), - MockPlatform.iOs(), - MockPlatform.macOs() + MockPlatform.iOS(), + MockPlatform.macOS() ]) { group('$SentryNativeBinding', () { late SentryNativeBinding sut; @@ -29,9 +29,9 @@ void main() { setUp(() { channel = MockMethodChannel(); - final options = - defaultTestOptions(getPlatformChecker(platform: mockPlatform)) - ..methodChannel = channel; + final options = defaultTestOptions() + ..platform = mockPlatform + ..methodChannel = channel; sut = createBinding(options); }); @@ -207,7 +207,7 @@ void main() { if (mockPlatform.isAndroid) { matcher = throwsUnsupportedError; } else if (mockPlatform.isIOS || mockPlatform.isMacOS) { - if (platform.instance.isMacOS) { + if (Platform().isMacOS) { matcher = throwsA(predicate((e) => e is Exception && e.toString().contains('Failed to load Objective-C class'))); diff --git a/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart b/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart index 9f5b0f9ed6..b77e83242d 100644 --- a/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart +++ b/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; // ignore_for_file: invalid_use_of_internal_member import 'package:flutter/cupertino.dart'; diff --git a/flutter/test/version_test.dart b/flutter/test/version_test.dart index b97fd250b4..90c861d5c9 100644 --- a/flutter/test/version_test.dart +++ b/flutter/test/version_test.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. @TestOn('vm') -library flutter_test; +library; import 'dart:io'; diff --git a/flutter/test/view_hierarchy/view_hierarchy_integration_test.dart b/flutter/test/view_hierarchy/view_hierarchy_integration_test.dart index c57fff8b5e..6c04ba5389 100644 --- a/flutter/test/view_hierarchy/view_hierarchy_integration_test.dart +++ b/flutter/test/view_hierarchy/view_hierarchy_integration_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/src/view_hierarchy/view_hierarchy_event_processor.dart'; diff --git a/flutter/test/web/html_utils.dart b/flutter/test/web/html_utils.dart deleted file mode 100644 index 9d1557a668..0000000000 --- a/flutter/test/web/html_utils.dart +++ /dev/null @@ -1,10 +0,0 @@ -// ignore: deprecated_member_use -import 'dart:html'; - -void injectMetaTag(Map attributes) { - final MetaElement meta = document.createElement('meta') as MetaElement; - for (final MapEntry attribute in attributes.entries) { - meta.setAttribute(attribute.key, attribute.value); - } - document.head!.append(meta); -} diff --git a/flutter/test/web/sentry_js_bundles_test.dart b/flutter/test/web/sentry_js_bundles_test.dart index a962f7231a..392b490bbf 100644 --- a/flutter/test/web/sentry_js_bundles_test.dart +++ b/flutter/test/web/sentry_js_bundles_test.dart @@ -1,5 +1,5 @@ @TestOn('browser') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart' as http; diff --git a/flutter/test/web/sentry_script_loader_test.dart b/flutter/test/web/sentry_script_loader_test.dart index ca17bede26..36c585dd07 100644 --- a/flutter/test/web/sentry_script_loader_test.dart +++ b/flutter/test/web/sentry_script_loader_test.dart @@ -1,5 +1,5 @@ @TestOn('browser') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/src/web/script_loader/script_dom_api.dart'; diff --git a/flutter/test/web/sentry_script_loader_tt_custom_test.dart b/flutter/test/web/sentry_script_loader_tt_custom_test.dart index 19f8601b14..9b53476dd4 100644 --- a/flutter/test/web/sentry_script_loader_tt_custom_test.dart +++ b/flutter/test/web/sentry_script_loader_tt_custom_test.dart @@ -1,5 +1,5 @@ @TestOn('browser') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/src/web/script_loader/sentry_script_loader.dart'; diff --git a/flutter/test/web/sentry_script_loader_tt_forbidden_test.dart b/flutter/test/web/sentry_script_loader_tt_forbidden_test.dart index 29123caad2..e64c67b5c8 100644 --- a/flutter/test/web/sentry_script_loader_tt_forbidden_test.dart +++ b/flutter/test/web/sentry_script_loader_tt_forbidden_test.dart @@ -1,5 +1,5 @@ @TestOn('browser') -library flutter_test; +library; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/src/web/script_loader/sentry_script_loader.dart'; diff --git a/flutter/test/web/sentry_web_test.dart b/flutter/test/web/sentry_web_test.dart index c3d1496a17..6a85dfe622 100644 --- a/flutter/test/web/sentry_web_test.dart +++ b/flutter/test/web/sentry_web_test.dart @@ -1,5 +1,5 @@ @TestOn('browser') -library flutter_test; +library; import 'dart:typed_data'; @@ -42,47 +42,46 @@ void main() { await sut.close(); }); - // TODO: re-enable this test in V9 - // test('init: options mapped to JS SDK', () async { - // const expectedDsn = 'https://random@def.ingest.sentry.io/1234567'; - // const expectedRelease = 'my-random-release'; - // const expectedSampleRate = 0.2; - // const expectedEnv = 'my-random-env'; - // const expectedDist = '999'; - // const expectedAttachStacktrace = false; - // const expectedMaxBreadcrumbs = 1000; - // const expectedDebug = true; - // - // options.dsn = expectedDsn; - // options.release = expectedRelease; - // options.sampleRate = expectedSampleRate; - // options.environment = expectedEnv; - // options.dist = expectedDist; - // options.attachStacktrace = expectedAttachStacktrace; - // options.maxBreadcrumbs = expectedMaxBreadcrumbs; - // options.debug = expectedDebug; - // - // // quick check that Sentry is not initialized first - // expect(() => binding.getJsOptions()['dsn'], throwsA(anything)); - // - // await sut.init(hub); - // - // final jsOptions = binding.getJsOptions(); - // - // expect(jsOptions['dsn'], expectedDsn); - // expect(jsOptions['release'], expectedRelease); - // expect(jsOptions['sampleRate'], expectedSampleRate); - // expect(jsOptions['environment'], expectedEnv); - // expect(jsOptions['dist'], expectedDist); - // expect(jsOptions['attachStacktrace'], expectedAttachStacktrace); - // expect(jsOptions['maxBreadcrumbs'], expectedMaxBreadcrumbs); - // expect(jsOptions['debug'], expectedDebug); - // expect(jsOptions['defaultIntegrations'].length, 2); - // expect(jsOptions['defaultIntegrations'][0].toString(), - // contains('name: GlobalHandlers')); - // expect(jsOptions['defaultIntegrations'][1].toString(), - // contains('name: Dedupe')); - // }); + test('init: options mapped to JS SDK', () async { + const expectedDsn = 'https://random@def.ingest.sentry.io/1234567'; + const expectedRelease = 'my-random-release'; + const expectedSampleRate = 0.2; + const expectedEnv = 'my-random-env'; + const expectedDist = '999'; + const expectedAttachStacktrace = false; + const expectedMaxBreadcrumbs = 1000; + const expectedDebug = true; + + options.dsn = expectedDsn; + options.release = expectedRelease; + options.sampleRate = expectedSampleRate; + options.environment = expectedEnv; + options.dist = expectedDist; + options.attachStacktrace = expectedAttachStacktrace; + options.maxBreadcrumbs = expectedMaxBreadcrumbs; + options.debug = expectedDebug; + + // quick check that Sentry is not initialized first + expect(() => binding.getJsOptions()['dsn'], throwsA(anything)); + + await sut.init(hub); + + final jsOptions = binding.getJsOptions(); + + expect(jsOptions['dsn'], expectedDsn); + expect(jsOptions['release'], expectedRelease); + expect(jsOptions['sampleRate'], expectedSampleRate); + expect(jsOptions['environment'], expectedEnv); + expect(jsOptions['dist'], expectedDist); + expect(jsOptions['attachStacktrace'], expectedAttachStacktrace); + expect(jsOptions['maxBreadcrumbs'], expectedMaxBreadcrumbs); + expect(jsOptions['debug'], expectedDebug); + expect(jsOptions['defaultIntegrations'].length, 2); + expect(jsOptions['defaultIntegrations'][0].toString(), + contains('name: GlobalHandlers')); + expect(jsOptions['defaultIntegrations'][1].toString(), + contains('name: Dedupe')); + }); test('options getter returns the original options', () { expect(sut.options, same(options)); diff --git a/flutter/test/web/utils.dart b/flutter/test/web/utils.dart index 81fc6af0c7..bd8481ed26 100644 --- a/flutter/test/web/utils.dart +++ b/flutter/test/web/utils.dart @@ -1,6 +1,28 @@ +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; import 'package:sentry_flutter/src/web/script_loader/script_dom_api.dart'; +import 'package:web/web.dart'; -export 'html_utils.dart' if (dart.library.js_interop) 'web_utils.dart'; +void injectMetaTag(Map attributes) { + final HTMLMetaElement meta = + document.createElement('meta') as HTMLMetaElement; + for (final MapEntry attribute in attributes.entries) { + meta.setAttribute(attribute.key, attribute.value); + } + document.head!.appendChild(meta); +} + +@JS('Sentry') +external JSObject? get sentry; + +dynamic getJsOptions() { + final client = sentry?.callMethod('getClient'.toJS, null) as JSObject?; + if (client == null) { + return null; + } + final options = client.callMethod('getOptions'.toJS, null); + return options?.dartify(); +} List fetchAllScripts() { return fetchScripts('script'); diff --git a/flutter/test/web/web_utils.dart b/flutter/test/web/web_utils.dart deleted file mode 100644 index 53ec33f6b3..0000000000 --- a/flutter/test/web/web_utils.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'dart:js_interop'; -import 'dart:js_interop_unsafe'; - -// ignore: depend_on_referenced_packages -import 'package:web/web.dart'; - -void injectMetaTag(Map attributes) { - final HTMLMetaElement meta = - document.createElement('meta') as HTMLMetaElement; - for (final MapEntry attribute in attributes.entries) { - meta.setAttribute(attribute.key, attribute.value); - } - document.head!.appendChild(meta); -} - -@JS('Sentry') -external JSObject? get sentry; - -dynamic getJsOptions() { - final client = sentry?.callMethod('getClient'.toJS, null) as JSObject?; - if (client == null) { - return null; - } - final options = client.callMethod('getOptions'.toJS, null); - return options?.dartify(); -} diff --git a/hive/lib/sentry_hive.dart b/hive/lib/sentry_hive.dart index 03be720ca1..740ae6a1bf 100644 --- a/hive/lib/sentry_hive.dart +++ b/hive/lib/sentry_hive.dart @@ -1,4 +1,4 @@ -library sentry_hive; +library; import 'package:meta/meta.dart'; import 'package:hive/hive.dart'; diff --git a/hive/lib/src/sentry_box_collection.dart b/hive/lib/src/sentry_box_collection.dart index 0dee9e9831..48f28f60f1 100644 --- a/hive/lib/src/sentry_box_collection.dart +++ b/hive/lib/src/sentry_box_collection.dart @@ -1,18 +1,15 @@ import 'package:hive/hive.dart'; -import 'package:meta/meta.dart'; -import 'package:sentry/sentry.dart'; - -import 'sentry_span_helper.dart'; - -// ignore: implementation_imports -import 'package:hive/src/box_collection/box_collection_stub.dart' as stub; - // ignore: implementation_imports import 'package:hive/src/box_collection/box_collection_stub.dart' - if (dart.library.html) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.js_interop) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.io) 'package:hive/src/box_collection/box_collection.dart' as impl; +// ignore: implementation_imports +import 'package:hive/src/box_collection/box_collection_stub.dart' as stub; +import 'package:meta/meta.dart'; +import 'package:sentry/sentry.dart'; + +import 'sentry_span_helper.dart'; /// Use instead of [BoxCollection] to add automatic tracing. class SentryBoxCollection implements stub.BoxCollection { diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 8c537ec1c2..3ba08240e4 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.14.0'; +const String sdkVersion = '9.0.0-alpha.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 30e5800e50..7934e863fe 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,12 +1,12 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 8.14.0 +version: 9.0.0-alpha.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues environment: - sdk: '>=2.17.0 <4.0.0' + sdk: '>=3.5.0 <4.0.0' platforms: android: @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.14.0 + sentry: 9.0.0-alpha.1 hive: ^2.2.3 meta: ^1.3.0 diff --git a/hive/test/mocks/mocks.dart b/hive/test/mocks/mocks.dart index 8b6d7f4db9..5853473cac 100644 --- a/hive/test/mocks/mocks.dart +++ b/hive/test/mocks/mocks.dart @@ -1,12 +1,10 @@ import 'package:hive/hive.dart'; -import 'package:mockito/annotations.dart'; -import 'package:sentry/sentry.dart'; - import 'package:hive/src/box_collection/box_collection_stub.dart' - if (dart.library.html) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.js_interop) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.io) 'package:hive/src/box_collection/box_collection.dart' as impl; +import 'package:mockito/annotations.dart'; +import 'package:sentry/sentry.dart'; @GenerateMocks([ Hub, diff --git a/hive/test/mocks/mocks.mocks.dart b/hive/test/mocks/mocks.mocks.dart index 5cd8fc7e30..c972b7d196 100644 --- a/hive/test/mocks/mocks.mocks.dart +++ b/hive/test/mocks/mocks.mocks.dart @@ -1,117 +1,79 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.5 from annotations // in sentry_hive/test/mocks/mocks.dart. // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i5; -import 'dart:typed_data' as _i8; +import 'dart:typed_data' as _i9; import 'package:hive/hive.dart' as _i3; -import 'package:hive/src/box/default_compaction_strategy.dart' as _i7; -import 'package:hive/src/box/default_key_comparator.dart' as _i6; -import 'package:mockito/mockito.dart' as _i1; -import 'package:sentry/sentry.dart' as _i2; -import 'package:sentry/src/profiling.dart' as _i4; - -import 'package:hive/src/box_collection/box_collection_stub.dart' as stub; - +import 'package:hive/src/box/default_compaction_strategy.dart' as _i8; +import 'package:hive/src/box/default_key_comparator.dart' as _i7; // ignore: implementation_imports import 'package:hive/src/box_collection/box_collection_stub.dart' if (dart.library.html) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.js_interop) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.io) 'package:hive/src/box_collection/box_collection.dart' as impl; +import 'package:hive/src/box_collection/box_collection_stub.dart' as stub; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i6; +import 'package:sentry/sentry.dart' as _i2; +import 'package:sentry/src/profiling.dart' as _i4; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class class _FakeSentryOptions_0 extends _i1.SmartFake implements _i2.SentryOptions { - _FakeSentryOptions_0( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeSentryOptions_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeSentryId_1 extends _i1.SmartFake implements _i2.SentryId { - _FakeSentryId_1( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeSentryId_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeScope_2 extends _i1.SmartFake implements _i2.Scope { - _FakeScope_2( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeScope_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeHub_3 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_3( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeHub_3(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeISentrySpan_4 extends _i1.SmartFake implements _i2.ISentrySpan { - _FakeISentrySpan_4( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeISentrySpan_4(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeBox_5 extends _i1.SmartFake implements _i3.Box { - _FakeBox_5( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeBox_5(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeLazyBox_6 extends _i1.SmartFake implements _i3.LazyBox { - _FakeLazyBox_6( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeLazyBox_6(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeCollectionBox_7 extends _i1.SmartFake implements _i3.CollectionBox { - _FakeCollectionBox_7( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeCollectionBox_7(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } /// A class which mocks [Hub]. @@ -132,41 +94,31 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.SentryOptions); @override - bool get isEnabled => (super.noSuchMethod( - Invocation.getter(#isEnabled), - returnValue: false, - ) as bool); + bool get isEnabled => + (super.noSuchMethod(Invocation.getter(#isEnabled), returnValue: false) + as bool); @override _i2.SentryId get lastEventId => (super.noSuchMethod( Invocation.getter(#lastEventId), - returnValue: _FakeSentryId_1( - this, - Invocation.getter(#lastEventId), - ), + returnValue: _FakeSentryId_1(this, Invocation.getter(#lastEventId)), ) as _i2.SentryId); @override _i2.Scope get scope => (super.noSuchMethod( Invocation.getter(#scope), - returnValue: _FakeScope_2( - this, - Invocation.getter(#scope), - ), + returnValue: _FakeScope_2(this, Invocation.getter(#scope)), ) as _i2.Scope); @override set profilerFactory(_i4.SentryProfilerFactory? value) => super.noSuchMethod( - Invocation.setter( - #profilerFactory, - value, - ), + Invocation.setter(#profilerFactory, value), returnValueForMissingStub: null, ); @override _i5.Future<_i2.SentryId> captureEvent( - dynamic event, { + _i2.SentryEvent? event, { dynamic stackTrace, _i2.Hint? hint, _i2.ScopeCallback? withScope, @@ -175,24 +127,18 @@ class MockHub extends _i1.Mock implements _i2.Hub { Invocation.method( #captureEvent, [event], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, - ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( - this, - Invocation.method( - #captureEvent, - [event], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), + returnValue: _i5.Future<_i2.SentryId>.value( + _FakeSentryId_1( + this, + Invocation.method( + #captureEvent, + [event], + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), ), - )), + ), ) as _i5.Future<_i2.SentryId>); @override @@ -206,24 +152,18 @@ class MockHub extends _i1.Mock implements _i2.Hub { Invocation.method( #captureException, [throwable], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, - ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( - this, - Invocation.method( - #captureException, - [throwable], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), + returnValue: _i5.Future<_i2.SentryId>.value( + _FakeSentryId_1( + this, + Invocation.method( + #captureException, + [throwable], + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), ), - )), + ), ) as _i5.Future<_i2.SentryId>); @override @@ -247,88 +187,79 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( - this, - Invocation.method( - #captureMessage, - [message], - { - #level: level, - #template: template, - #params: params, - #hint: hint, - #withScope: withScope, - }, + returnValue: _i5.Future<_i2.SentryId>.value( + _FakeSentryId_1( + this, + Invocation.method( + #captureMessage, + [message], + { + #level: level, + #template: template, + #params: params, + #hint: hint, + #withScope: withScope, + }, + ), ), - )), + ), ) as _i5.Future<_i2.SentryId>); @override - _i5.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => + _i5.Future<_i2.SentryId> captureFeedback( + _i2.SentryFeedback? feedback, { + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => (super.noSuchMethod( Invocation.method( - #captureUserFeedback, - [userFeedback], + #captureFeedback, + [feedback], + {#hint: hint, #withScope: withScope}, + ), + returnValue: _i5.Future<_i2.SentryId>.value( + _FakeSentryId_1( + this, + Invocation.method( + #captureFeedback, + [feedback], + {#hint: hint, #withScope: withScope}, + ), + ), ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + ) as _i5.Future<_i2.SentryId>); @override - _i5.Future addBreadcrumb( - _i2.Breadcrumb? crumb, { - _i2.Hint? hint, - }) => + _i5.Future addBreadcrumb(_i2.Breadcrumb? crumb, {_i2.Hint? hint}) => (super.noSuchMethod( - Invocation.method( - #addBreadcrumb, - [crumb], - {#hint: hint}, - ), + Invocation.method(#addBreadcrumb, [crumb], {#hint: hint}), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override void bindClient(_i2.SentryClient? client) => super.noSuchMethod( - Invocation.method( - #bindClient, - [client], - ), + Invocation.method(#bindClient, [client]), returnValueForMissingStub: null, ); @override _i2.Hub clone() => (super.noSuchMethod( - Invocation.method( - #clone, - [], - ), - returnValue: _FakeHub_3( - this, - Invocation.method( - #clone, - [], - ), - ), + Invocation.method(#clone, []), + returnValue: _FakeHub_3(this, Invocation.method(#clone, [])), ) as _i2.Hub); @override _i5.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], - ), + Invocation.method(#close, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.FutureOr configureScope(_i2.ScopeCallback? callback) => - (super.noSuchMethod(Invocation.method( - #configureScope, - [callback], - )) as _i5.FutureOr); + (super.noSuchMethod(Invocation.method(#configureScope, [callback])) + as _i5.FutureOr); @override _i2.ISentrySpan startTransaction( @@ -346,10 +277,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { (super.noSuchMethod( Invocation.method( #startTransaction, - [ - name, - operation, - ], + [name, operation], { #description: description, #startTimestamp: startTimestamp, @@ -365,10 +293,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { this, Invocation.method( #startTransaction, - [ - name, - operation, - ], + [name, operation], { #description: description, #startTimestamp: startTimestamp, @@ -430,21 +355,24 @@ class MockHub extends _i1.Mock implements _i2.Hub { _i5.Future<_i2.SentryId> captureTransaction( _i2.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, - ), - returnValue: _i5.Future<_i2.SentryId>.value(_FakeSentryId_1( - this, - Invocation.method( - #captureTransaction, - [transaction], - {#traceContext: traceContext}, + {#traceContext: traceContext, #hint: hint}, + ), + returnValue: _i5.Future<_i2.SentryId>.value( + _FakeSentryId_1( + this, + Invocation.method( + #captureTransaction, + [transaction], + {#traceContext: traceContext, #hint: hint}, + ), ), - )), + ), ) as _i5.Future<_i2.SentryId>); @override @@ -454,14 +382,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { String? transaction, ) => super.noSuchMethod( - Invocation.method( - #setSpanContext, - [ - throwable, - span, - transaction, - ], - ), + Invocation.method(#setSpanContext, [throwable, span, transaction]), returnValueForMissingStub: null, ); } @@ -475,247 +396,165 @@ class MockBox extends _i1.Mock implements _i3.Box { } @override - Iterable get values => (super.noSuchMethod( - Invocation.getter(#values), - returnValue: [], - ) as Iterable); + Iterable get values => + (super.noSuchMethod(Invocation.getter(#values), returnValue: []) + as Iterable); @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i6.dummyValue(this, Invocation.getter(#name)), ) as String); @override - bool get isOpen => (super.noSuchMethod( - Invocation.getter(#isOpen), - returnValue: false, - ) as bool); + bool get isOpen => + (super.noSuchMethod(Invocation.getter(#isOpen), returnValue: false) + as bool); @override - bool get lazy => (super.noSuchMethod( - Invocation.getter(#lazy), - returnValue: false, - ) as bool); + bool get lazy => + (super.noSuchMethod(Invocation.getter(#lazy), returnValue: false) + as bool); @override - Iterable get keys => (super.noSuchMethod( - Invocation.getter(#keys), - returnValue: [], - ) as Iterable); + Iterable get keys => + (super.noSuchMethod(Invocation.getter(#keys), returnValue: []) + as Iterable); @override - int get length => (super.noSuchMethod( - Invocation.getter(#length), - returnValue: 0, - ) as int); + int get length => + (super.noSuchMethod(Invocation.getter(#length), returnValue: 0) as int); @override - bool get isEmpty => (super.noSuchMethod( - Invocation.getter(#isEmpty), - returnValue: false, - ) as bool); + bool get isEmpty => + (super.noSuchMethod(Invocation.getter(#isEmpty), returnValue: false) + as bool); @override - bool get isNotEmpty => (super.noSuchMethod( - Invocation.getter(#isNotEmpty), - returnValue: false, - ) as bool); + bool get isNotEmpty => + (super.noSuchMethod(Invocation.getter(#isNotEmpty), returnValue: false) + as bool); @override - Iterable valuesBetween({ - dynamic startKey, - dynamic endKey, - }) => + Iterable valuesBetween({dynamic startKey, dynamic endKey}) => (super.noSuchMethod( - Invocation.method( - #valuesBetween, - [], - { - #startKey: startKey, - #endKey: endKey, - }, - ), + Invocation.method(#valuesBetween, [], { + #startKey: startKey, + #endKey: endKey, + }), returnValue: [], ) as Iterable); @override - E? getAt(int? index) => (super.noSuchMethod(Invocation.method( - #getAt, - [index], - )) as E?); + E? getAt(int? index) => + (super.noSuchMethod(Invocation.method(#getAt, [index])) as E?); @override Map toMap() => (super.noSuchMethod( - Invocation.method( - #toMap, - [], - ), + Invocation.method(#toMap, []), returnValue: {}, ) as Map); @override - dynamic keyAt(int? index) => super.noSuchMethod(Invocation.method( - #keyAt, - [index], - )); + dynamic keyAt(int? index) => + super.noSuchMethod(Invocation.method(#keyAt, [index])); @override _i5.Stream<_i3.BoxEvent> watch({dynamic key}) => (super.noSuchMethod( - Invocation.method( - #watch, - [], - {#key: key}, - ), + Invocation.method(#watch, [], {#key: key}), returnValue: _i5.Stream<_i3.BoxEvent>.empty(), ) as _i5.Stream<_i3.BoxEvent>); @override bool containsKey(dynamic key) => (super.noSuchMethod( - Invocation.method( - #containsKey, - [key], - ), + Invocation.method(#containsKey, [key]), returnValue: false, ) as bool); @override - _i5.Future put( - dynamic key, - E? value, - ) => - (super.noSuchMethod( - Invocation.method( - #put, - [ - key, - value, - ], - ), + _i5.Future put(dynamic key, E? value) => (super.noSuchMethod( + Invocation.method(#put, [key, value]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override - _i5.Future putAt( - int? index, - E? value, - ) => - (super.noSuchMethod( - Invocation.method( - #putAt, - [ - index, - value, - ], - ), + _i5.Future putAt(int? index, E? value) => (super.noSuchMethod( + Invocation.method(#putAt, [index, value]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future putAll(Map? entries) => (super.noSuchMethod( - Invocation.method( - #putAll, - [entries], - ), + Invocation.method(#putAll, [entries]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future add(E? value) => (super.noSuchMethod( - Invocation.method( - #add, - [value], - ), + Invocation.method(#add, [value]), returnValue: _i5.Future.value(0), ) as _i5.Future); @override _i5.Future> addAll(Iterable? values) => (super.noSuchMethod( - Invocation.method( - #addAll, - [values], - ), + Invocation.method(#addAll, [values]), returnValue: _i5.Future>.value([]), ) as _i5.Future>); @override _i5.Future delete(dynamic key) => (super.noSuchMethod( - Invocation.method( - #delete, - [key], - ), + Invocation.method(#delete, [key]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future deleteAt(int? index) => (super.noSuchMethod( - Invocation.method( - #deleteAt, - [index], - ), + Invocation.method(#deleteAt, [index]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future deleteAll(Iterable? keys) => (super.noSuchMethod( - Invocation.method( - #deleteAll, - [keys], - ), + Invocation.method(#deleteAll, [keys]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future compact() => (super.noSuchMethod( - Invocation.method( - #compact, - [], - ), + Invocation.method(#compact, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future clear() => (super.noSuchMethod( - Invocation.method( - #clear, - [], - ), + Invocation.method(#clear, []), returnValue: _i5.Future.value(0), ) as _i5.Future); @override _i5.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], - ), + Invocation.method(#close, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future deleteFromDisk() => (super.noSuchMethod( - Invocation.method( - #deleteFromDisk, - [], - ), + Invocation.method(#deleteFromDisk, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future flush() => (super.noSuchMethod( - Invocation.method( - #flush, - [], - ), + Invocation.method(#flush, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @@ -732,230 +571,150 @@ class MockLazyBox extends _i1.Mock implements _i3.LazyBox { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i6.dummyValue(this, Invocation.getter(#name)), ) as String); @override - bool get isOpen => (super.noSuchMethod( - Invocation.getter(#isOpen), - returnValue: false, - ) as bool); + bool get isOpen => + (super.noSuchMethod(Invocation.getter(#isOpen), returnValue: false) + as bool); @override - bool get lazy => (super.noSuchMethod( - Invocation.getter(#lazy), - returnValue: false, - ) as bool); + bool get lazy => + (super.noSuchMethod(Invocation.getter(#lazy), returnValue: false) + as bool); @override - Iterable get keys => (super.noSuchMethod( - Invocation.getter(#keys), - returnValue: [], - ) as Iterable); + Iterable get keys => + (super.noSuchMethod(Invocation.getter(#keys), returnValue: []) + as Iterable); @override - int get length => (super.noSuchMethod( - Invocation.getter(#length), - returnValue: 0, - ) as int); + int get length => + (super.noSuchMethod(Invocation.getter(#length), returnValue: 0) as int); @override - bool get isEmpty => (super.noSuchMethod( - Invocation.getter(#isEmpty), - returnValue: false, - ) as bool); + bool get isEmpty => + (super.noSuchMethod(Invocation.getter(#isEmpty), returnValue: false) + as bool); @override - bool get isNotEmpty => (super.noSuchMethod( - Invocation.getter(#isNotEmpty), - returnValue: false, - ) as bool); + bool get isNotEmpty => + (super.noSuchMethod(Invocation.getter(#isNotEmpty), returnValue: false) + as bool); @override - _i5.Future get( - dynamic key, { - E? defaultValue, - }) => - (super.noSuchMethod( - Invocation.method( - #get, - [key], - {#defaultValue: defaultValue}, - ), + _i5.Future get(dynamic key, {E? defaultValue}) => (super.noSuchMethod( + Invocation.method(#get, [key], {#defaultValue: defaultValue}), returnValue: _i5.Future.value(), ) as _i5.Future); @override _i5.Future getAt(int? index) => (super.noSuchMethod( - Invocation.method( - #getAt, - [index], - ), + Invocation.method(#getAt, [index]), returnValue: _i5.Future.value(), ) as _i5.Future); @override - dynamic keyAt(int? index) => super.noSuchMethod(Invocation.method( - #keyAt, - [index], - )); + dynamic keyAt(int? index) => + super.noSuchMethod(Invocation.method(#keyAt, [index])); @override _i5.Stream<_i3.BoxEvent> watch({dynamic key}) => (super.noSuchMethod( - Invocation.method( - #watch, - [], - {#key: key}, - ), + Invocation.method(#watch, [], {#key: key}), returnValue: _i5.Stream<_i3.BoxEvent>.empty(), ) as _i5.Stream<_i3.BoxEvent>); @override bool containsKey(dynamic key) => (super.noSuchMethod( - Invocation.method( - #containsKey, - [key], - ), + Invocation.method(#containsKey, [key]), returnValue: false, ) as bool); @override - _i5.Future put( - dynamic key, - E? value, - ) => - (super.noSuchMethod( - Invocation.method( - #put, - [ - key, - value, - ], - ), + _i5.Future put(dynamic key, E? value) => (super.noSuchMethod( + Invocation.method(#put, [key, value]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override - _i5.Future putAt( - int? index, - E? value, - ) => - (super.noSuchMethod( - Invocation.method( - #putAt, - [ - index, - value, - ], - ), + _i5.Future putAt(int? index, E? value) => (super.noSuchMethod( + Invocation.method(#putAt, [index, value]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future putAll(Map? entries) => (super.noSuchMethod( - Invocation.method( - #putAll, - [entries], - ), + Invocation.method(#putAll, [entries]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future add(E? value) => (super.noSuchMethod( - Invocation.method( - #add, - [value], - ), + Invocation.method(#add, [value]), returnValue: _i5.Future.value(0), ) as _i5.Future); @override _i5.Future> addAll(Iterable? values) => (super.noSuchMethod( - Invocation.method( - #addAll, - [values], - ), + Invocation.method(#addAll, [values]), returnValue: _i5.Future>.value([]), ) as _i5.Future>); @override _i5.Future delete(dynamic key) => (super.noSuchMethod( - Invocation.method( - #delete, - [key], - ), + Invocation.method(#delete, [key]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future deleteAt(int? index) => (super.noSuchMethod( - Invocation.method( - #deleteAt, - [index], - ), + Invocation.method(#deleteAt, [index]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future deleteAll(Iterable? keys) => (super.noSuchMethod( - Invocation.method( - #deleteAll, - [keys], - ), + Invocation.method(#deleteAll, [keys]), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future compact() => (super.noSuchMethod( - Invocation.method( - #compact, - [], - ), + Invocation.method(#compact, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future clear() => (super.noSuchMethod( - Invocation.method( - #clear, - [], - ), + Invocation.method(#clear, []), returnValue: _i5.Future.value(0), ) as _i5.Future); @override _i5.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], - ), + Invocation.method(#close, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future deleteFromDisk() => (super.noSuchMethod( - Invocation.method( - #deleteFromDisk, - [], - ), + Invocation.method(#deleteFromDisk, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future flush() => (super.noSuchMethod( - Invocation.method( - #flush, - [], - ), + Invocation.method(#flush, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @@ -977,10 +736,7 @@ class MockHiveInterface extends _i1.Mock implements _i3.HiveInterface { }) => super.noSuchMethod( Invocation.method( - #init, - [path], - {#backendPreference: backendPreference}, - ), + #init, [path], {#backendPreference: backendPreference}), returnValueForMissingStub: null, ); @@ -988,11 +744,11 @@ class MockHiveInterface extends _i1.Mock implements _i3.HiveInterface { _i5.Future<_i3.Box> openBox( String? name, { _i3.HiveCipher? encryptionCipher, - _i3.KeyComparator? keyComparator = _i6.defaultKeyComparator, - _i3.CompactionStrategy? compactionStrategy = _i7.defaultCompactionStrategy, + _i3.KeyComparator? keyComparator = _i7.defaultKeyComparator, + _i3.CompactionStrategy? compactionStrategy = _i8.defaultCompactionStrategy, bool? crashRecovery = true, String? path, - _i8.Uint8List? bytes, + _i9.Uint8List? bytes, String? collection, List? encryptionKey, }) => @@ -1011,31 +767,33 @@ class MockHiveInterface extends _i1.Mock implements _i3.HiveInterface { #encryptionKey: encryptionKey, }, ), - returnValue: _i5.Future<_i3.Box>.value(_FakeBox_5( - this, - Invocation.method( - #openBox, - [name], - { - #encryptionCipher: encryptionCipher, - #keyComparator: keyComparator, - #compactionStrategy: compactionStrategy, - #crashRecovery: crashRecovery, - #path: path, - #bytes: bytes, - #collection: collection, - #encryptionKey: encryptionKey, - }, + returnValue: _i5.Future<_i3.Box>.value( + _FakeBox_5( + this, + Invocation.method( + #openBox, + [name], + { + #encryptionCipher: encryptionCipher, + #keyComparator: keyComparator, + #compactionStrategy: compactionStrategy, + #crashRecovery: crashRecovery, + #path: path, + #bytes: bytes, + #collection: collection, + #encryptionKey: encryptionKey, + }, + ), ), - )), + ), ) as _i5.Future<_i3.Box>); @override _i5.Future<_i3.LazyBox> openLazyBox( String? name, { _i3.HiveCipher? encryptionCipher, - _i3.KeyComparator? keyComparator = _i6.defaultKeyComparator, - _i3.CompactionStrategy? compactionStrategy = _i7.defaultCompactionStrategy, + _i3.KeyComparator? keyComparator = _i7.defaultKeyComparator, + _i3.CompactionStrategy? compactionStrategy = _i8.defaultCompactionStrategy, bool? crashRecovery = true, String? path, String? collection, @@ -1055,127 +813,85 @@ class MockHiveInterface extends _i1.Mock implements _i3.HiveInterface { #encryptionKey: encryptionKey, }, ), - returnValue: _i5.Future<_i3.LazyBox>.value(_FakeLazyBox_6( - this, - Invocation.method( - #openLazyBox, - [name], - { - #encryptionCipher: encryptionCipher, - #keyComparator: keyComparator, - #compactionStrategy: compactionStrategy, - #crashRecovery: crashRecovery, - #path: path, - #collection: collection, - #encryptionKey: encryptionKey, - }, + returnValue: _i5.Future<_i3.LazyBox>.value( + _FakeLazyBox_6( + this, + Invocation.method( + #openLazyBox, + [name], + { + #encryptionCipher: encryptionCipher, + #keyComparator: keyComparator, + #compactionStrategy: compactionStrategy, + #crashRecovery: crashRecovery, + #path: path, + #collection: collection, + #encryptionKey: encryptionKey, + }, + ), ), - )), + ), ) as _i5.Future<_i3.LazyBox>); @override _i3.Box box(String? name) => (super.noSuchMethod( - Invocation.method( - #box, - [name], - ), - returnValue: _FakeBox_5( - this, - Invocation.method( - #box, - [name], - ), - ), + Invocation.method(#box, [name]), + returnValue: _FakeBox_5(this, Invocation.method(#box, [name])), ) as _i3.Box); @override _i3.LazyBox lazyBox(String? name) => (super.noSuchMethod( - Invocation.method( - #lazyBox, - [name], - ), + Invocation.method(#lazyBox, [name]), returnValue: _FakeLazyBox_6( this, - Invocation.method( - #lazyBox, - [name], - ), + Invocation.method(#lazyBox, [name]), ), ) as _i3.LazyBox); @override bool isBoxOpen(String? name) => (super.noSuchMethod( - Invocation.method( - #isBoxOpen, - [name], - ), + Invocation.method(#isBoxOpen, [name]), returnValue: false, ) as bool); @override _i5.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], - ), + Invocation.method(#close, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override - _i5.Future deleteBoxFromDisk( - String? name, { - String? path, - }) => + _i5.Future deleteBoxFromDisk(String? name, {String? path}) => (super.noSuchMethod( - Invocation.method( - #deleteBoxFromDisk, - [name], - {#path: path}, - ), + Invocation.method(#deleteBoxFromDisk, [name], {#path: path}), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override _i5.Future deleteFromDisk() => (super.noSuchMethod( - Invocation.method( - #deleteFromDisk, - [], - ), + Invocation.method(#deleteFromDisk, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override List generateSecureKey() => (super.noSuchMethod( - Invocation.method( - #generateSecureKey, - [], - ), + Invocation.method(#generateSecureKey, []), returnValue: [], ) as List); @override - _i5.Future boxExists( - String? name, { - String? path, - }) => + _i5.Future boxExists(String? name, {String? path}) => (super.noSuchMethod( - Invocation.method( - #boxExists, - [name], - {#path: path}, - ), + Invocation.method(#boxExists, [name], {#path: path}), returnValue: _i5.Future.value(false), ) as _i5.Future); @override void resetAdapters() => super.noSuchMethod( - Invocation.method( - #resetAdapters, - [], - ), + Invocation.method(#resetAdapters, []), returnValueForMissingStub: null, ); @@ -1189,29 +905,20 @@ class MockHiveInterface extends _i1.Mock implements _i3.HiveInterface { Invocation.method( #registerAdapter, [adapter], - { - #internal: internal, - #override: override, - }, + {#internal: internal, #override: override}, ), returnValueForMissingStub: null, ); @override bool isAdapterRegistered(int? typeId) => (super.noSuchMethod( - Invocation.method( - #isAdapterRegistered, - [typeId], - ), + Invocation.method(#isAdapterRegistered, [typeId]), returnValue: false, ) as bool); @override void ignoreTypeId(int? typeId) => super.noSuchMethod( - Invocation.method( - #ignoreTypeId, - [typeId], - ), + Invocation.method(#ignoreTypeId, [typeId]), returnValueForMissingStub: null, ); } @@ -1227,45 +934,36 @@ class MockBoxCollection extends _i1.Mock implements impl.BoxCollection { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i6.dummyValue(this, Invocation.getter(#name)), ) as String); @override - Set get boxNames => (super.noSuchMethod( - Invocation.getter(#boxNames), - returnValue: {}, - ) as Set); + Set get boxNames => + (super.noSuchMethod(Invocation.getter(#boxNames), returnValue: {}) + as Set); @override _i5.Future> openBox( String? name, { bool? preload = false, - stub.CollectionBox Function( - String, - impl.BoxCollection, - )? boxCreator, + stub.CollectionBox Function(String, impl.BoxCollection)? boxCreator, }) => (super.noSuchMethod( Invocation.method( #openBox, [name], - { - #preload: preload, - #boxCreator: boxCreator, - }, - ), - returnValue: - _i5.Future>.value(_FakeCollectionBox_7( - this, - Invocation.method( - #openBox, - [name], - { - #preload: preload, - #boxCreator: boxCreator, - }, + {#preload: preload, #boxCreator: boxCreator}, + ), + returnValue: _i5.Future>.value( + _FakeCollectionBox_7( + this, + Invocation.method( + #openBox, + [name], + {#preload: preload, #boxCreator: boxCreator}, + ), ), - )), + ), ) as _i5.Future>); @override @@ -1278,10 +976,7 @@ class MockBoxCollection extends _i1.Mock implements impl.BoxCollection { Invocation.method( #transaction, [action], - { - #boxNames: boxNames, - #readOnly: readOnly, - }, + {#boxNames: boxNames, #readOnly: readOnly}, ), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), @@ -1289,19 +984,13 @@ class MockBoxCollection extends _i1.Mock implements impl.BoxCollection { @override void close() => super.noSuchMethod( - Invocation.method( - #close, - [], - ), + Invocation.method(#close, []), returnValueForMissingStub: null, ); @override _i5.Future deleteFromDisk() => (super.noSuchMethod( - Invocation.method( - #deleteFromDisk, - [], - ), + Invocation.method(#deleteFromDisk, []), returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); diff --git a/isar/lib/sentry_isar.dart b/isar/lib/sentry_isar.dart index 75e63c47ea..ca3d24ed45 100644 --- a/isar/lib/sentry_isar.dart +++ b/isar/lib/sentry_isar.dart @@ -1,4 +1,4 @@ -library sentry_isar; +library; export 'src/sentry_isar.dart'; export 'src/sentry_isar_collection.dart'; diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index a5132e9c22..10f45cc5a3 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.14.0'; +const String sdkVersion = '9.0.0-alpha.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index 2b37a697c9..7f87b3b40b 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,13 +1,13 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 8.14.0 +version: 9.0.0-alpha.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues environment: - sdk: '>=2.17.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '>=3.5.0 <4.0.0' + flutter: '>=3.24.0' platforms: android: @@ -20,7 +20,7 @@ platforms: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 8.14.0 + sentry: 9.0.0-alpha.1 meta: ^1.3.0 path: ^1.8.3 diff --git a/isar/test/mocks/mocks.mocks.dart b/isar/test/mocks/mocks.mocks.dart index dc4cbd87a4..0efd118833 100644 --- a/isar/test/mocks/mocks.mocks.dart +++ b/isar/test/mocks/mocks.mocks.dart @@ -1,8 +1,8 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in sentry_isar/test/mocks/mocks.dart. // Do not manually edit this file. -// ignore_for_file: no_leading_underscores_for_library_prefixes, invalid_use_of_internal_member +// ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; import 'dart:typed_data' as _i7; @@ -16,12 +16,15 @@ import 'package:sentry/src/profiling.dart' as _i5; // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member class _FakeSentryOptions_0 extends _i1.SmartFake implements _i2.SentryOptions { _FakeSentryOptions_0( @@ -286,16 +289,32 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i3.Future<_i2.SentryId>); @override - // ignore: deprecated_member_use - _i3.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => + _i3.Future<_i2.SentryId> captureFeedback( + _i2.SentryFeedback? feedback, { + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => (super.noSuchMethod( Invocation.method( - #captureUserFeedback, - [userFeedback], + #captureFeedback, + [feedback], + { + #hint: hint, + #withScope: withScope, + }, ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i3.Future<_i2.SentryId>.value(_FakeSentryId_1( + this, + Invocation.method( + #captureFeedback, + [feedback], + { + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i3.Future<_i2.SentryId>); @override _i3.Future addBreadcrumb( @@ -453,19 +472,26 @@ class MockHub extends _i1.Mock implements _i2.Hub { _i3.Future<_i2.SentryId> captureTransaction( _i2.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), returnValue: _i3.Future<_i2.SentryId>.value(_FakeSentryId_1( this, Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, + { + #traceContext: traceContext, + #hint: hint, + }, ), )), ) as _i3.Future<_i2.SentryId>); @@ -500,7 +526,10 @@ class MockIsar extends _i1.Mock implements _i4.Isar { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i6.dummyValue( + this, + Invocation.getter(#name), + ), ) as String); @override @@ -758,7 +787,10 @@ class MockIsarCollection extends _i1.Mock @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i6.dummyValue( + this, + Invocation.getter(#name), + ), ) as String); @override diff --git a/link/pubspec.yaml b/link/pubspec.yaml index 960a164855..b97ca7478b 100644 --- a/link/pubspec.yaml +++ b/link/pubspec.yaml @@ -1,19 +1,19 @@ name: sentry_link description: Automatic capture of exceptions and GraphQL errors for the gql eco-system, like graphql and ferry -version: 8.14.0 +version: 9.0.0-alpha.1 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues environment: - sdk: '>=3.0.0 <4.0.0' + sdk: '>=3.5.0 <4.0.0' dependencies: gql_error_link: ">=0.2.0 <2.0.0" gql_exec: ">=0.4.4 <2.0.0" gql_link: ">=0.5.0 <2.0.0" gql: ">=0.14.0 <2.0.0" - sentry: 8.14.0 + sentry: 9.0.0-alpha.1 dev_dependencies: lints: ^4.0.0 diff --git a/logging/lib/sentry_logging.dart b/logging/lib/sentry_logging.dart index 9b56c3f433..236f075583 100644 --- a/logging/lib/sentry_logging.dart +++ b/logging/lib/sentry_logging.dart @@ -1,3 +1,3 @@ -library sentry_logging; +library; export 'src/logging_integration.dart'; diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index de3dd61c88..bf8a74a766 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.14.0'; +const String sdkVersion = '9.0.0-alpha.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 9d5c80d7bd..fb52725432 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,13 +1,13 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 8.14.0 +version: 9.0.0-alpha.1 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues documentation: https://docs.sentry.io/platforms/dart/integrations/logging/ environment: - sdk: '>=2.17.0 <4.0.0' + sdk: '>=3.5.0 <4.0.0' platforms: android: @@ -19,7 +19,7 @@ platforms: dependencies: logging: ^1.0.0 - sentry: 8.14.0 + sentry: 9.0.0-alpha.1 dev_dependencies: lints: '>=2.0.0' diff --git a/logging/test/version_test.dart b/logging/test/version_test.dart index 316a1caaff..b9e5d69077 100644 --- a/logging/test/version_test.dart +++ b/logging/test/version_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library dart_test; +library; import 'dart:io'; diff --git a/metrics/prepare.sh b/metrics/prepare.sh index d492280af0..98d9ca0ee3 100755 --- a/metrics/prepare.sh +++ b/metrics/prepare.sh @@ -19,10 +19,6 @@ flutterCreate() { flutterCreate 'perf-test-app-plain' flutterCreate 'perf-test-app-with-sentry' -# bump minSdkVersion to 19 -gradleFile="$targetDir/perf-test-app-with-sentry/android/app/build.gradle" -sed "s/flutter.minSdkVersion/19/g" "$gradleFile" > "$gradleFile.new" && mv "$gradleFile.new" "$gradleFile" - echo '::group::Patch perf-test-app-with-sentry' pubspec="$targetDir/perf-test-app-with-sentry/pubspec_overrides.yaml" echo "Adding dependencies to $pubspec" diff --git a/min_version_test/android/app/build.gradle b/min_version_test/android/app/build.gradle index f183f2bfd5..2286767d8b 100644 --- a/min_version_test/android/app/build.gradle +++ b/min_version_test/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 33 + compileSdkVersion 34 ndkVersion '21.4.7075529' compileOptions { @@ -48,8 +48,8 @@ android { applicationId "com.example.minversiontest" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion 19 - targetSdkVersion 33 + minSdkVersion flutter.minSdkVersion + targetSdkVersion 34 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/min_version_test/lib/main.dart b/min_version_test/lib/main.dart index e1f182197a..9900260666 100644 --- a/min_version_test/lib/main.dart +++ b/min_version_test/lib/main.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; - import 'package:min_version_test/transaction/transaction_stub.dart' - if (dart.library.html) 'package:min_version_test/transaction/web_transaction.dart' if (dart.library.js_interop) 'package:min_version_test/transaction/web_transaction.dart' if (dart.library.io) 'package:min_version_test/transaction/file_transaction.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; @@ -12,32 +10,33 @@ const String _exampleDsn = 'https://e85b375ffb9f43cf8bdf9787768149e0@o447951.ingest.sentry.io/5428562'; Future main() async { - await setupSentry(() => runApp( - DefaultAssetBundle( - bundle: SentryAssetBundle(), - child: const MyApp(), - ), - )); + await setupSentry( + () => runApp( + DefaultAssetBundle(bundle: SentryAssetBundle(), child: const MyApp()), + ), + ); } Future setupSentry(AppRunner appRunner) async { - await SentryFlutter.init((options) { - options.dsn = _exampleDsn; - options.tracesSampleRate = 1.0; - options.attachThreads = true; - options.enableWindowMetricBreadcrumbs = true; - options.addIntegration(LoggingIntegration()); - options.sendDefaultPii = true; - options.reportSilentFlutterErrors = true; - options.attachScreenshot = true; - options.attachViewHierarchy = true; - // We can enable Sentry debug logging during development. This is likely - // going to log too much for your app, but can be useful when figuring out - // configuration issues, e.g. finding out why your events are not uploaded. - options.debug = true; - }, - // Init your App. - appRunner: appRunner); + await SentryFlutter.init( + (options) { + options.dsn = _exampleDsn; + options.tracesSampleRate = 1.0; + options.attachThreads = true; + options.enableWindowMetricBreadcrumbs = true; + options.addIntegration(LoggingIntegration()); + options.sendDefaultPii = true; + options.reportSilentFlutterErrors = true; + options.attachScreenshot = true; + options.attachViewHierarchy = true; + // We can enable Sentry debug logging during development. This is likely + // going to log too much for your app, but can be useful when figuring out + // configuration issues, e.g. finding out why your events are not uploaded. + options.debug = true; + }, + // Init your App. + appRunner: appRunner, + ); } class MyApp extends StatelessWidget { @@ -61,7 +60,8 @@ class MyApp extends StatelessWidget { primarySwatch: Colors.blue, ), home: SentryWidget( - child: const MyHomePage(title: 'Flutter Demo Home Page')), + child: const MyHomePage(title: 'Flutter Demo Home Page'), + ), ); } } @@ -135,9 +135,7 @@ class _MyHomePageState extends State { // horizontal). mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text( - 'You have pushed the button this many times:', - ), + const Text('You have pushed the button this many times:'), Text( '$_counter', // ignore: deprecated_member_use diff --git a/min_version_test/pubspec.yaml b/min_version_test/pubspec.yaml index e8e76dc9df..40bcc4a009 100644 --- a/min_version_test/pubspec.yaml +++ b/min_version_test/pubspec.yaml @@ -18,8 +18,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: '2.17.0' - flutter: '3.0.0' + sdk: '3.5.0' + flutter: '3.24.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -35,6 +35,7 @@ dependencies: dio: any # This gets constrained by `sentry_dio` logging: any # This gets constrained by `sentry_logging` + flutter: any dev_dependencies: flutter_test: sdk: flutter diff --git a/scripts/publish_validation/README.md b/scripts/publish_validation/README.md deleted file mode 100644 index e87d94c86d..0000000000 --- a/scripts/publish_validation/README.md +++ /dev/null @@ -1,3 +0,0 @@ -An internal command-line application to validate publish. -We temporarily need to use the `--skip-validation` flag in order to publish with backwards compatible WASM support. -Since we now don't have validations in place, this validation tool will catch unexpected errors that might occur during dry runs. \ No newline at end of file diff --git a/scripts/publish_validation/analysis_options.yaml b/scripts/publish_validation/analysis_options.yaml deleted file mode 100644 index 572dd239d0..0000000000 --- a/scripts/publish_validation/analysis_options.yaml +++ /dev/null @@ -1 +0,0 @@ -include: package:lints/recommended.yaml diff --git a/scripts/publish_validation/bin/publish_validation.dart b/scripts/publish_validation/bin/publish_validation.dart deleted file mode 100644 index fd8a93aef8..0000000000 --- a/scripts/publish_validation/bin/publish_validation.dart +++ /dev/null @@ -1,63 +0,0 @@ -import 'dart:io'; - -import 'package:args/args.dart'; - -void main(List arguments) async { - final parser = ArgParser() - ..addOption( - 'executable', - allowed: ['dart', 'flutter'], - defaultsTo: 'dart', - help: 'Specify the executable to use (dart or flutter)', - ); - - ArgResults args; - try { - args = parser.parse(arguments); - } on FormatException catch (e) { - print('Error: ${e.message}'); - print('Usage: dart script.dart [--executable ]'); - exit(1); - } - - final executable = args['executable'] as String; - - final result = await Process.run(executable, ['pub', 'publish', '--dry-run']); - final publishOutput = result.stderr as String; - - if (publishOutput.contains('Found no `pubspec.yaml` file')) { - print(publishOutput); - exit(1); - } - - const expectedErrors = [ - 'lib/src/integrations/connectivity/web_connectivity_provider.dart: This package does not have web in the `dependencies` section of `pubspec.yaml`', - 'lib/src/event_processor/enricher/web_enricher_event_processor.dart: This package does not have web in the `dependencies` section of `pubspec.yaml`', - 'lib/src/origin_web.dart: This package does not have web in the `dependencies` section of `pubspec.yaml`', - 'lib/src/platform/_web_platform.dart: This package does not have web in the `dependencies` section of `pubspec.yaml`', - 'lib/src/event_processor/url_filter/web_url_filter_event_processor.dart: This package does not have web in the `dependencies` section of `pubspec.yaml`', - 'lib/src/web/script_loader/web_script_dom_api.dart: This package does not have web in the `dependencies` section of `pubspec.yaml`', - 'test/web/dom_api/web_script_dom_api.dart: This package does not have web in the `dependencies` or `dev_dependencies` section of `pubspec.yaml`', - 'test/web/web_utils.dart: This package does not have web in the `dependencies` or `dev_dependencies` section of `pubspec.yaml`', - ]; - - // So far the expected errors all start with `* line` - final errorLines = publishOutput - .split('\n') - .where((line) => line.startsWith('* line')) - .toList(); - - final unexpectedErrors = errorLines.where((errorLine) { - return !expectedErrors - .any((expectedError) => errorLine.contains(expectedError)); - }).toList(); - - if (unexpectedErrors.isEmpty) { - print('Only expected errors found. Validation passed.'); - exit(0); - } else { - print('Unexpected errors found:'); - unexpectedErrors.forEach(print); - exit(1); - } -} diff --git a/scripts/publish_validation/pubspec.yaml b/scripts/publish_validation/pubspec.yaml deleted file mode 100644 index a8dd96a670..0000000000 --- a/scripts/publish_validation/pubspec.yaml +++ /dev/null @@ -1,13 +0,0 @@ -name: publish_validation -description: Command-line application for validating publish dry runs. -publish_to: none - -environment: - sdk: ^3.4.3 - -dependencies: - args: ^2.5.0 - -dev_dependencies: - lints: ^3.0.0 - test: ^1.24.0 diff --git a/sqflite/lib/sentry_sqflite.dart b/sqflite/lib/sentry_sqflite.dart index 770831fb5b..a09ff17490 100644 --- a/sqflite/lib/sentry_sqflite.dart +++ b/sqflite/lib/sentry_sqflite.dart @@ -1,4 +1,4 @@ -library sentry_sqflite; +library; export 'src/sentry_database.dart'; export 'src/sentry_sqflite.dart'; diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 6a17a33abd..cdb6385834 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.14.0'; +const String sdkVersion = '9.0.0-alpha.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index 645ddbb8de..694ff50991 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,13 +1,13 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 8.14.0 +version: 9.0.0-alpha.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues environment: - sdk: '>=2.17.0 <4.0.0' - flutter: '>=3.3.0' # matching sqflite + sdk: '>=3.5.0 <4.0.0' + flutter: '>=3.24.0' platforms: android: @@ -15,7 +15,7 @@ platforms: macos: dependencies: - sentry: 8.14.0 + sentry: 9.0.0-alpha.1 sqflite: ^2.2.8 sqflite_common: ^2.0.0 meta: ^1.3.0 diff --git a/sqflite/test/mocks/mocks.mocks.dart b/sqflite/test/mocks/mocks.mocks.dart index 11300b2dff..a7a3118fcf 100644 --- a/sqflite/test/mocks/mocks.mocks.dart +++ b/sqflite/test/mocks/mocks.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.5 from annotations // in sentry_sqflite/test/mocks/mocks.dart. // Do not manually edit this file. @@ -6,151 +6,95 @@ import 'dart:async' as _i4; import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i7; +import 'package:mockito/src/dummies.dart' as _i6; import 'package:sentry/sentry.dart' as _i2; +import 'package:sentry/src/profiling.dart' as _i7; import 'package:sentry/src/sentry_tracer.dart' as _i5; -import 'package:sqflite_common/sql.dart' as _i6; +import 'package:sqflite_common/sql.dart' as _i8; import 'package:sqflite_common/sqlite_api.dart' as _i3; -import 'mocks.dart' as _i8; +import 'mocks.dart' as _i9; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member class _FakeSentrySpanContext_0 extends _i1.SmartFake implements _i2.SentrySpanContext { - _FakeSentrySpanContext_0( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeSentrySpanContext_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeDateTime_1 extends _i1.SmartFake implements DateTime { - _FakeDateTime_1( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeDateTime_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeISentrySpan_2 extends _i1.SmartFake implements _i2.ISentrySpan { - _FakeISentrySpan_2( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeISentrySpan_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeSentryTraceHeader_3 extends _i1.SmartFake implements _i2.SentryTraceHeader { - _FakeSentryTraceHeader_3( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeSentryTraceHeader_3(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeDatabase_4 extends _i1.SmartFake implements _i3.Database { - _FakeDatabase_4( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeDatabase_4(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeFuture_5 extends _i1.SmartFake implements _i4.Future { - _FakeFuture_5( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeFuture_5(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeQueryCursor_6 extends _i1.SmartFake implements _i3.QueryCursor { - _FakeQueryCursor_6( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeQueryCursor_6(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeBatch_7 extends _i1.SmartFake implements _i3.Batch { - _FakeBatch_7( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeBatch_7(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeSentryOptions_8 extends _i1.SmartFake implements _i2.SentryOptions { - _FakeSentryOptions_8( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeSentryOptions_8(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeSentryId_9 extends _i1.SmartFake implements _i2.SentryId { - _FakeSentryId_9( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeSentryId_9(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeScope_10 extends _i1.SmartFake implements _i2.Scope { - _FakeScope_10( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeScope_10(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakeHub_11 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_11( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakeHub_11(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } /// A class which mocks [SentryTracer]. /// /// See the documentation for Mockito's code generation for more information. -// ignore: invalid_use_of_internal_member class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { MockSentryTracer() { _i1.throwOnMissingStub(this); @@ -159,32 +103,49 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i6.dummyValue(this, Invocation.getter(#name)), ) as String); + @override set name(String? _name) => super.noSuchMethod( - Invocation.setter( - #name, - _name, - ), + Invocation.setter(#name, _name), returnValueForMissingStub: null, ); + @override _i2.SentryTransactionNameSource get transactionNameSource => (super.noSuchMethod( Invocation.getter(#transactionNameSource), returnValue: _i2.SentryTransactionNameSource.custom, ) as _i2.SentryTransactionNameSource); + @override set transactionNameSource( - _i2.SentryTransactionNameSource? _transactionNameSource) => + _i2.SentryTransactionNameSource? _transactionNameSource, + ) => super.noSuchMethod( - Invocation.setter( - #transactionNameSource, - _transactionNameSource, - ), + Invocation.setter(#transactionNameSource, _transactionNameSource), returnValueForMissingStub: null, ); + + @override + set profiler(_i7.SentryProfiler? _profiler) => super.noSuchMethod( + Invocation.setter(#profiler, _profiler), + returnValueForMissingStub: null, + ); + + @override + set profileInfo(_i7.SentryProfileInfo? _profileInfo) => super.noSuchMethod( + Invocation.setter(#profileInfo, _profileInfo), + returnValueForMissingStub: null, + ); + + @override + Map get measurements => (super.noSuchMethod( + Invocation.getter(#measurements), + returnValue: {}, + ) as Map); + @override _i2.SentrySpanContext get context => (super.noSuchMethod( Invocation.getter(#context), @@ -193,14 +154,13 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { Invocation.getter(#context), ), ) as _i2.SentrySpanContext); + @override set origin(String? origin) => super.noSuchMethod( - Invocation.setter( - #origin, - origin, - ), + Invocation.setter(#origin, origin), returnValueForMissingStub: null, ); + @override DateTime get startTimestamp => (super.noSuchMethod( Invocation.getter(#startTimestamp), @@ -209,110 +169,82 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { Invocation.getter(#startTimestamp), ), ) as DateTime); + @override Map get data => (super.noSuchMethod( Invocation.getter(#data), returnValue: {}, ) as Map); + @override - bool get finished => (super.noSuchMethod( - Invocation.getter(#finished), - returnValue: false, - ) as bool); + bool get finished => + (super.noSuchMethod(Invocation.getter(#finished), returnValue: false) + as bool); + @override List<_i2.SentrySpan> get children => (super.noSuchMethod( Invocation.getter(#children), returnValue: <_i2.SentrySpan>[], ) as List<_i2.SentrySpan>); + @override set throwable(dynamic throwable) => super.noSuchMethod( - Invocation.setter( - #throwable, - throwable, - ), + Invocation.setter(#throwable, throwable), returnValueForMissingStub: null, ); + @override set status(_i2.SpanStatus? status) => super.noSuchMethod( - Invocation.setter( - #status, - status, - ), + Invocation.setter(#status, status), returnValueForMissingStub: null, ); + @override Map get tags => (super.noSuchMethod( Invocation.getter(#tags), returnValue: {}, ) as Map); - @override - Map get measurements => (super.noSuchMethod( - Invocation.getter(#measurements), - returnValue: {}, - ) as Map); + @override _i4.Future finish({ _i2.SpanStatus? status, DateTime? endTimestamp, + _i2.Hint? hint, }) => (super.noSuchMethod( - Invocation.method( - #finish, - [], - { - #status: status, - #endTimestamp: endTimestamp, - }, - ), + Invocation.method(#finish, [], { + #status: status, + #endTimestamp: endTimestamp, + #hint: hint, + }), returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override void removeData(String? key) => super.noSuchMethod( - Invocation.method( - #removeData, - [key], - ), + Invocation.method(#removeData, [key]), returnValueForMissingStub: null, ); + @override void removeTag(String? key) => super.noSuchMethod( - Invocation.method( - #removeTag, - [key], - ), + Invocation.method(#removeTag, [key]), returnValueForMissingStub: null, ); + @override - void setData( - String? key, - dynamic value, - ) => - super.noSuchMethod( - Invocation.method( - #setData, - [ - key, - value, - ], - ), + void setData(String? key, dynamic value) => super.noSuchMethod( + Invocation.method(#setData, [key, value]), returnValueForMissingStub: null, ); + @override - void setTag( - String? key, - String? value, - ) => - super.noSuchMethod( - Invocation.method( - #setTag, - [ - key, - value, - ], - ), + void setTag(String? key, String? value) => super.noSuchMethod( + Invocation.method(#setTag, [key, value]), returnValueForMissingStub: null, ); + @override _i2.ISentrySpan startChild( String? operation, { @@ -323,23 +255,18 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { Invocation.method( #startChild, [operation], - { - #description: description, - #startTimestamp: startTimestamp, - }, + {#description: description, #startTimestamp: startTimestamp}, ), returnValue: _FakeISentrySpan_2( this, Invocation.method( #startChild, [operation], - { - #description: description, - #startTimestamp: startTimestamp, - }, + {#description: description, #startTimestamp: startTimestamp}, ), ), ) as _i2.ISentrySpan); + @override _i2.ISentrySpan startChildWithParentSpanId( _i2.SpanId? parentSpanId, @@ -350,67 +277,54 @@ class MockSentryTracer extends _i1.Mock implements _i5.SentryTracer { (super.noSuchMethod( Invocation.method( #startChildWithParentSpanId, - [ - parentSpanId, - operation, - ], - { - #description: description, - #startTimestamp: startTimestamp, - }, + [parentSpanId, operation], + {#description: description, #startTimestamp: startTimestamp}, ), returnValue: _FakeISentrySpan_2( this, Invocation.method( #startChildWithParentSpanId, - [ - parentSpanId, - operation, - ], - { - #description: description, - #startTimestamp: startTimestamp, - }, + [parentSpanId, operation], + {#description: description, #startTimestamp: startTimestamp}, ), ), ) as _i2.ISentrySpan); + @override _i2.SentryTraceHeader toSentryTrace() => (super.noSuchMethod( - Invocation.method( - #toSentryTrace, - [], - ), + Invocation.method(#toSentryTrace, []), returnValue: _FakeSentryTraceHeader_3( this, - Invocation.method( - #toSentryTrace, - [], - ), + Invocation.method(#toSentryTrace, []), ), ) as _i2.SentryTraceHeader); + @override void setMeasurement( String? name, num? value, { _i2.SentryMeasurementUnit? unit, + }) => + super.noSuchMethod( + Invocation.method(#setMeasurement, [name, value], {#unit: unit}), + returnValueForMissingStub: null, + ); + + @override + void setMeasurementFromChild( + String? name, + num? value, { + _i2.SentryMeasurementUnit? unit, }) => super.noSuchMethod( Invocation.method( - #setMeasurement, - [ - name, - value, - ], - {#unit: unit}, - ), + #setMeasurementFromChild, [name, value], {#unit: unit}), returnValueForMissingStub: null, ); + @override void scheduleFinish() => super.noSuchMethod( - Invocation.method( - #scheduleFinish, - [], - ), + Invocation.method(#scheduleFinish, []), returnValueForMissingStub: null, ); } @@ -424,10 +338,9 @@ class MockBatch extends _i1.Mock implements _i3.Batch { } @override - int get length => (super.noSuchMethod( - Invocation.getter(#length), - returnValue: 0, - ) as int); + int get length => + (super.noSuchMethod(Invocation.getter(#length), returnValue: 0) as int); + @override _i4.Future> commit({ bool? exclusive, @@ -435,99 +348,67 @@ class MockBatch extends _i1.Mock implements _i3.Batch { bool? continueOnError, }) => (super.noSuchMethod( - Invocation.method( - #commit, - [], - { - #exclusive: exclusive, - #noResult: noResult, - #continueOnError: continueOnError, - }, - ), + Invocation.method(#commit, [], { + #exclusive: exclusive, + #noResult: noResult, + #continueOnError: continueOnError, + }), returnValue: _i4.Future>.value([]), ) as _i4.Future>); + @override - _i4.Future> apply({ - bool? noResult, - bool? continueOnError, - }) => + _i4.Future> apply({bool? noResult, bool? continueOnError}) => (super.noSuchMethod( - Invocation.method( - #apply, - [], - { - #noResult: noResult, - #continueOnError: continueOnError, - }, - ), + Invocation.method(#apply, [], { + #noResult: noResult, + #continueOnError: continueOnError, + }), returnValue: _i4.Future>.value([]), ) as _i4.Future>); + @override - void rawInsert( - String? sql, [ - List? arguments, - ]) => - super.noSuchMethod( - Invocation.method( - #rawInsert, - [ - sql, - arguments, - ], - ), + void rawInsert(String? sql, [List? arguments]) => super.noSuchMethod( + Invocation.method(#rawInsert, [sql, arguments]), returnValueForMissingStub: null, ); + @override void insert( String? table, Map? values, { String? nullColumnHack, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i8.ConflictAlgorithm? conflictAlgorithm, }) => super.noSuchMethod( Invocation.method( #insert, - [ - table, - values, - ], + [table, values], { #nullColumnHack: nullColumnHack, - #conflictAlgorithm: conflictAlgorithm, + #conflictAlgorithm: conflictAlgorithm }, ), returnValueForMissingStub: null, ); + @override - void rawUpdate( - String? sql, [ - List? arguments, - ]) => - super.noSuchMethod( - Invocation.method( - #rawUpdate, - [ - sql, - arguments, - ], - ), + void rawUpdate(String? sql, [List? arguments]) => super.noSuchMethod( + Invocation.method(#rawUpdate, [sql, arguments]), returnValueForMissingStub: null, ); + @override void update( String? table, Map? values, { String? where, List? whereArgs, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i8.ConflictAlgorithm? conflictAlgorithm, }) => super.noSuchMethod( Invocation.method( #update, - [ - table, - values, - ], + [table, values], { #where: where, #whereArgs: whereArgs, @@ -536,53 +417,30 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValueForMissingStub: null, ); + @override - void rawDelete( - String? sql, [ - List? arguments, - ]) => - super.noSuchMethod( - Invocation.method( - #rawDelete, - [ - sql, - arguments, - ], - ), + void rawDelete(String? sql, [List? arguments]) => super.noSuchMethod( + Invocation.method(#rawDelete, [sql, arguments]), returnValueForMissingStub: null, ); + @override - void delete( - String? table, { - String? where, - List? whereArgs, - }) => + void delete(String? table, {String? where, List? whereArgs}) => super.noSuchMethod( Invocation.method( #delete, [table], - { - #where: where, - #whereArgs: whereArgs, - }, + {#where: where, #whereArgs: whereArgs}, ), returnValueForMissingStub: null, ); + @override - void execute( - String? sql, [ - List? arguments, - ]) => - super.noSuchMethod( - Invocation.method( - #execute, - [ - sql, - arguments, - ], - ), + void execute(String? sql, [List? arguments]) => super.noSuchMethod( + Invocation.method(#execute, [sql, arguments]), returnValueForMissingStub: null, ); + @override void query( String? table, { @@ -614,19 +472,10 @@ class MockBatch extends _i1.Mock implements _i3.Batch { ), returnValueForMissingStub: null, ); + @override - void rawQuery( - String? sql, [ - List? arguments, - ]) => - super.noSuchMethod( - Invocation.method( - #rawQuery, - [ - sql, - arguments, - ], - ), + void rawQuery(String? sql, [List? arguments]) => super.noSuchMethod( + Invocation.method(#rawQuery, [sql, arguments]), returnValueForMissingStub: null, ); } @@ -642,43 +491,36 @@ class MockDatabase extends _i1.Mock implements _i3.Database { @override String get path => (super.noSuchMethod( Invocation.getter(#path), - returnValue: '', + returnValue: _i6.dummyValue(this, Invocation.getter(#path)), ) as String); + @override - bool get isOpen => (super.noSuchMethod( - Invocation.getter(#isOpen), - returnValue: false, - ) as bool); + bool get isOpen => + (super.noSuchMethod(Invocation.getter(#isOpen), returnValue: false) + as bool); + @override _i3.Database get database => (super.noSuchMethod( Invocation.getter(#database), - returnValue: _FakeDatabase_4( - this, - Invocation.getter(#database), - ), + returnValue: _FakeDatabase_4(this, Invocation.getter(#database)), ) as _i3.Database); + @override _i4.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], - ), + Invocation.method(#close, []), returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.Future transaction( _i4.Future Function(_i3.Transaction)? action, { bool? exclusive, }) => (super.noSuchMethod( - Invocation.method( - #transaction, - [action], - {#exclusive: exclusive}, - ), - returnValue: _i7.ifNotNull( - _i7.dummyValueOrNull( + Invocation.method(#transaction, [action], {#exclusive: exclusive}), + returnValue: _i6.ifNotNull( + _i6.dummyValueOrNull( this, Invocation.method( #transaction, @@ -697,43 +539,43 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), ), ) as _i4.Future); + @override - _i4.Future devInvokeMethod( - String? method, [ - Object? arguments, - ]) => + _i4.Future readTransaction( + _i4.Future Function(_i3.Transaction)? action, + ) => (super.noSuchMethod( - Invocation.method( - #devInvokeMethod, - [ - method, - arguments, - ], - ), - returnValue: _i7.ifNotNull( - _i7.dummyValueOrNull( + Invocation.method(#readTransaction, [action]), + returnValue: _i6.ifNotNull( + _i6.dummyValueOrNull( this, - Invocation.method( - #devInvokeMethod, - [ - method, - arguments, - ], - ), + Invocation.method(#readTransaction, [action]), ), (T v) => _i4.Future.value(v), ) ?? _FakeFuture_5( this, - Invocation.method( - #devInvokeMethod, - [ - method, - arguments, - ], + Invocation.method(#readTransaction, [action]), + ), + ) as _i4.Future); + + @override + _i4.Future devInvokeMethod(String? method, [Object? arguments]) => + (super.noSuchMethod( + Invocation.method(#devInvokeMethod, [method, arguments]), + returnValue: _i6.ifNotNull( + _i6.dummyValueOrNull( + this, + Invocation.method(#devInvokeMethod, [method, arguments]), ), + (T v) => _i4.Future.value(v), + ) ?? + _FakeFuture_5( + this, + Invocation.method(#devInvokeMethod, [method, arguments]), ), ) as _i4.Future); + @override _i4.Future devInvokeSqlMethod( String? method, @@ -741,85 +583,54 @@ class MockDatabase extends _i1.Mock implements _i3.Database { List? arguments, ]) => (super.noSuchMethod( - Invocation.method( - #devInvokeSqlMethod, - [ - method, - sql, - arguments, - ], - ), - returnValue: _i7.ifNotNull( - _i7.dummyValueOrNull( + Invocation.method(#devInvokeSqlMethod, [method, sql, arguments]), + returnValue: _i6.ifNotNull( + _i6.dummyValueOrNull( this, - Invocation.method( - #devInvokeSqlMethod, - [ - method, - sql, - arguments, - ], - ), + Invocation.method(#devInvokeSqlMethod, [ + method, + sql, + arguments, + ]), ), (T v) => _i4.Future.value(v), ) ?? _FakeFuture_5( this, - Invocation.method( - #devInvokeSqlMethod, - [ - method, - sql, - arguments, - ], - ), + Invocation.method(#devInvokeSqlMethod, [ + method, + sql, + arguments, + ]), ), ) as _i4.Future); + @override - _i4.Future execute( - String? sql, [ - List? arguments, - ]) => + _i4.Future execute(String? sql, [List? arguments]) => (super.noSuchMethod( - Invocation.method( - #execute, - [ - sql, - arguments, - ], - ), + Invocation.method(#execute, [sql, arguments]), returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override - _i4.Future rawInsert( - String? sql, [ - List? arguments, - ]) => + _i4.Future rawInsert(String? sql, [List? arguments]) => (super.noSuchMethod( - Invocation.method( - #rawInsert, - [ - sql, - arguments, - ], - ), + Invocation.method(#rawInsert, [sql, arguments]), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future insert( String? table, Map? values, { String? nullColumnHack, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i8.ConflictAlgorithm? conflictAlgorithm, }) => (super.noSuchMethod( Invocation.method( #insert, - [ - table, - values, - ], + [table, values], { #nullColumnHack: nullColumnHack, #conflictAlgorithm: conflictAlgorithm, @@ -827,6 +638,7 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future>> query( String? table, { @@ -857,24 +669,22 @@ class MockDatabase extends _i1.Mock implements _i3.Database { }, ), returnValue: _i4.Future>>.value( - >[]), + >[], + ), ) as _i4.Future>>); + @override _i4.Future>> rawQuery( String? sql, [ List? arguments, ]) => (super.noSuchMethod( - Invocation.method( - #rawQuery, - [ - sql, - arguments, - ], - ), + Invocation.method(#rawQuery, [sql, arguments]), returnValue: _i4.Future>>.value( - >[]), + >[], + ), ) as _i4.Future>>); + @override _i4.Future<_i3.QueryCursor> rawQueryCursor( String? sql, @@ -884,24 +694,21 @@ class MockDatabase extends _i1.Mock implements _i3.Database { (super.noSuchMethod( Invocation.method( #rawQueryCursor, - [ - sql, - arguments, - ], + [sql, arguments], {#bufferSize: bufferSize}, ), - returnValue: _i4.Future<_i3.QueryCursor>.value(_FakeQueryCursor_6( - this, - Invocation.method( - #rawQueryCursor, - [ - sql, - arguments, - ], - {#bufferSize: bufferSize}, + returnValue: _i4.Future<_i3.QueryCursor>.value( + _FakeQueryCursor_6( + this, + Invocation.method( + #rawQueryCursor, + [sql, arguments], + {#bufferSize: bufferSize}, + ), ), - )), + ), ) as _i4.Future<_i3.QueryCursor>); + @override _i4.Future<_i3.QueryCursor> queryCursor( String? table, { @@ -933,56 +740,48 @@ class MockDatabase extends _i1.Mock implements _i3.Database { #bufferSize: bufferSize, }, ), - returnValue: _i4.Future<_i3.QueryCursor>.value(_FakeQueryCursor_6( - this, - Invocation.method( - #queryCursor, - [table], - { - #distinct: distinct, - #columns: columns, - #where: where, - #whereArgs: whereArgs, - #groupBy: groupBy, - #having: having, - #orderBy: orderBy, - #limit: limit, - #offset: offset, - #bufferSize: bufferSize, - }, + returnValue: _i4.Future<_i3.QueryCursor>.value( + _FakeQueryCursor_6( + this, + Invocation.method( + #queryCursor, + [table], + { + #distinct: distinct, + #columns: columns, + #where: where, + #whereArgs: whereArgs, + #groupBy: groupBy, + #having: having, + #orderBy: orderBy, + #limit: limit, + #offset: offset, + #bufferSize: bufferSize, + }, + ), ), - )), + ), ) as _i4.Future<_i3.QueryCursor>); + @override - _i4.Future rawUpdate( - String? sql, [ - List? arguments, - ]) => + _i4.Future rawUpdate(String? sql, [List? arguments]) => (super.noSuchMethod( - Invocation.method( - #rawUpdate, - [ - sql, - arguments, - ], - ), + Invocation.method(#rawUpdate, [sql, arguments]), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future update( String? table, Map? values, { String? where, List? whereArgs, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i8.ConflictAlgorithm? conflictAlgorithm, }) => (super.noSuchMethod( Invocation.method( #update, - [ - table, - values, - ], + [table, values], { #where: where, #whereArgs: whereArgs, @@ -991,21 +790,14 @@ class MockDatabase extends _i1.Mock implements _i3.Database { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override - _i4.Future rawDelete( - String? sql, [ - List? arguments, - ]) => + _i4.Future rawDelete(String? sql, [List? arguments]) => (super.noSuchMethod( - Invocation.method( - #rawDelete, - [ - sql, - arguments, - ], - ), + Invocation.method(#rawDelete, [sql, arguments]), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future delete( String? table, { @@ -1016,26 +808,15 @@ class MockDatabase extends _i1.Mock implements _i3.Database { Invocation.method( #delete, [table], - { - #where: where, - #whereArgs: whereArgs, - }, + {#where: where, #whereArgs: whereArgs}, ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i3.Batch batch() => (super.noSuchMethod( - Invocation.method( - #batch, - [], - ), - returnValue: _FakeBatch_7( - this, - Invocation.method( - #batch, - [], - ), - ), + Invocation.method(#batch, []), + returnValue: _FakeBatch_7(this, Invocation.method(#batch, [])), ) as _i3.Batch); } @@ -1050,56 +831,35 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { @override _i3.Database get database => (super.noSuchMethod( Invocation.getter(#database), - returnValue: _FakeDatabase_4( - this, - Invocation.getter(#database), - ), + returnValue: _FakeDatabase_4(this, Invocation.getter(#database)), ) as _i3.Database); + @override - _i4.Future execute( - String? sql, [ - List? arguments, - ]) => + _i4.Future execute(String? sql, [List? arguments]) => (super.noSuchMethod( - Invocation.method( - #execute, - [ - sql, - arguments, - ], - ), + Invocation.method(#execute, [sql, arguments]), returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override - _i4.Future rawInsert( - String? sql, [ - List? arguments, - ]) => + _i4.Future rawInsert(String? sql, [List? arguments]) => (super.noSuchMethod( - Invocation.method( - #rawInsert, - [ - sql, - arguments, - ], - ), + Invocation.method(#rawInsert, [sql, arguments]), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future insert( String? table, Map? values, { String? nullColumnHack, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i8.ConflictAlgorithm? conflictAlgorithm, }) => (super.noSuchMethod( Invocation.method( #insert, - [ - table, - values, - ], + [table, values], { #nullColumnHack: nullColumnHack, #conflictAlgorithm: conflictAlgorithm, @@ -1107,6 +867,7 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future>> query( String? table, { @@ -1137,24 +898,22 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { }, ), returnValue: _i4.Future>>.value( - >[]), + >[], + ), ) as _i4.Future>>); + @override _i4.Future>> rawQuery( String? sql, [ List? arguments, ]) => (super.noSuchMethod( - Invocation.method( - #rawQuery, - [ - sql, - arguments, - ], - ), + Invocation.method(#rawQuery, [sql, arguments]), returnValue: _i4.Future>>.value( - >[]), + >[], + ), ) as _i4.Future>>); + @override _i4.Future<_i3.QueryCursor> rawQueryCursor( String? sql, @@ -1164,24 +923,21 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { (super.noSuchMethod( Invocation.method( #rawQueryCursor, - [ - sql, - arguments, - ], + [sql, arguments], {#bufferSize: bufferSize}, ), - returnValue: _i4.Future<_i3.QueryCursor>.value(_FakeQueryCursor_6( - this, - Invocation.method( - #rawQueryCursor, - [ - sql, - arguments, - ], - {#bufferSize: bufferSize}, + returnValue: _i4.Future<_i3.QueryCursor>.value( + _FakeQueryCursor_6( + this, + Invocation.method( + #rawQueryCursor, + [sql, arguments], + {#bufferSize: bufferSize}, + ), ), - )), + ), ) as _i4.Future<_i3.QueryCursor>); + @override _i4.Future<_i3.QueryCursor> queryCursor( String? table, { @@ -1213,56 +969,48 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { #bufferSize: bufferSize, }, ), - returnValue: _i4.Future<_i3.QueryCursor>.value(_FakeQueryCursor_6( - this, - Invocation.method( - #queryCursor, - [table], - { - #distinct: distinct, - #columns: columns, - #where: where, - #whereArgs: whereArgs, - #groupBy: groupBy, - #having: having, - #orderBy: orderBy, - #limit: limit, - #offset: offset, - #bufferSize: bufferSize, - }, + returnValue: _i4.Future<_i3.QueryCursor>.value( + _FakeQueryCursor_6( + this, + Invocation.method( + #queryCursor, + [table], + { + #distinct: distinct, + #columns: columns, + #where: where, + #whereArgs: whereArgs, + #groupBy: groupBy, + #having: having, + #orderBy: orderBy, + #limit: limit, + #offset: offset, + #bufferSize: bufferSize, + }, + ), ), - )), + ), ) as _i4.Future<_i3.QueryCursor>); + @override - _i4.Future rawUpdate( - String? sql, [ - List? arguments, - ]) => + _i4.Future rawUpdate(String? sql, [List? arguments]) => (super.noSuchMethod( - Invocation.method( - #rawUpdate, - [ - sql, - arguments, - ], - ), + Invocation.method(#rawUpdate, [sql, arguments]), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future update( String? table, Map? values, { String? where, List? whereArgs, - _i6.ConflictAlgorithm? conflictAlgorithm, + _i8.ConflictAlgorithm? conflictAlgorithm, }) => (super.noSuchMethod( Invocation.method( #update, - [ - table, - values, - ], + [table, values], { #where: where, #whereArgs: whereArgs, @@ -1271,21 +1019,14 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override - _i4.Future rawDelete( - String? sql, [ - List? arguments, - ]) => + _i4.Future rawDelete(String? sql, [List? arguments]) => (super.noSuchMethod( - Invocation.method( - #rawDelete, - [ - sql, - arguments, - ], - ), + Invocation.method(#rawDelete, [sql, arguments]), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i4.Future delete( String? table, { @@ -1296,26 +1037,15 @@ class MockDatabaseExecutor extends _i1.Mock implements _i3.DatabaseExecutor { Invocation.method( #delete, [table], - { - #where: where, - #whereArgs: whereArgs, - }, + {#where: where, #whereArgs: whereArgs}, ), returnValue: _i4.Future.value(0), ) as _i4.Future); + @override _i3.Batch batch() => (super.noSuchMethod( - Invocation.method( - #batch, - [], - ), - returnValue: _FakeBatch_7( - this, - Invocation.method( - #batch, - [], - ), - ), + Invocation.method(#batch, []), + returnValue: _FakeBatch_7(this, Invocation.method(#batch, [])), ) as _i3.Batch); } @@ -1335,27 +1065,30 @@ class MockHub extends _i1.Mock implements _i2.Hub { Invocation.getter(#options), ), ) as _i2.SentryOptions); + @override - bool get isEnabled => (super.noSuchMethod( - Invocation.getter(#isEnabled), - returnValue: false, - ) as bool); + bool get isEnabled => + (super.noSuchMethod(Invocation.getter(#isEnabled), returnValue: false) + as bool); + @override _i2.SentryId get lastEventId => (super.noSuchMethod( Invocation.getter(#lastEventId), - returnValue: _FakeSentryId_9( - this, - Invocation.getter(#lastEventId), - ), + returnValue: _FakeSentryId_9(this, Invocation.getter(#lastEventId)), ) as _i2.SentryId); + @override _i2.Scope get scope => (super.noSuchMethod( Invocation.getter(#scope), - returnValue: _FakeScope_10( - this, - Invocation.getter(#scope), - ), + returnValue: _FakeScope_10(this, Invocation.getter(#scope)), ) as _i2.Scope); + + @override + set profilerFactory(_i7.SentryProfilerFactory? value) => super.noSuchMethod( + Invocation.setter(#profilerFactory, value), + returnValueForMissingStub: null, + ); + @override _i4.Future<_i2.SentryId> captureEvent( _i2.SentryEvent? event, { @@ -1367,25 +1100,20 @@ class MockHub extends _i1.Mock implements _i2.Hub { Invocation.method( #captureEvent, [event], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, - ), - returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_9( - this, - Invocation.method( - #captureEvent, - [event], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), + returnValue: _i4.Future<_i2.SentryId>.value( + _FakeSentryId_9( + this, + Invocation.method( + #captureEvent, + [event], + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), ), - )), + ), ) as _i4.Future<_i2.SentryId>); + @override _i4.Future<_i2.SentryId> captureException( dynamic throwable, { @@ -1397,25 +1125,20 @@ class MockHub extends _i1.Mock implements _i2.Hub { Invocation.method( #captureException, [throwable], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, - ), - returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_9( - this, - Invocation.method( - #captureException, - [throwable], - { - #stackTrace: stackTrace, - #hint: hint, - #withScope: withScope, - }, + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), + returnValue: _i4.Future<_i2.SentryId>.value( + _FakeSentryId_9( + this, + Invocation.method( + #captureException, + [throwable], + {#stackTrace: stackTrace, #hint: hint, #withScope: withScope}, + ), ), - )), + ), ) as _i4.Future<_i2.SentryId>); + @override _i4.Future<_i2.SentryId> captureMessage( String? message, { @@ -1437,83 +1160,80 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_9( - this, - Invocation.method( - #captureMessage, - [message], - { - #level: level, - #template: template, - #params: params, - #hint: hint, - #withScope: withScope, - }, + returnValue: _i4.Future<_i2.SentryId>.value( + _FakeSentryId_9( + this, + Invocation.method( + #captureMessage, + [message], + { + #level: level, + #template: template, + #params: params, + #hint: hint, + #withScope: withScope, + }, + ), ), - )), - ) as _i4.Future<_i2.SentryId>); - @override - // ignore: deprecated_member_use - _i4.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => - (super.noSuchMethod( - Invocation.method( - #captureUserFeedback, - [userFeedback], ), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) as _i4.Future); + ) as _i4.Future<_i2.SentryId>); + @override - _i4.Future addBreadcrumb( - _i2.Breadcrumb? crumb, { + _i4.Future<_i2.SentryId> captureFeedback( + _i2.SentryFeedback? feedback, { _i2.Hint? hint, + _i2.ScopeCallback? withScope, }) => (super.noSuchMethod( Invocation.method( - #addBreadcrumb, - [crumb], - {#hint: hint}, + #captureFeedback, + [feedback], + {#hint: hint, #withScope: withScope}, + ), + returnValue: _i4.Future<_i2.SentryId>.value( + _FakeSentryId_9( + this, + Invocation.method( + #captureFeedback, + [feedback], + {#hint: hint, #withScope: withScope}, + ), + ), ), + ) as _i4.Future<_i2.SentryId>); + + @override + _i4.Future addBreadcrumb(_i2.Breadcrumb? crumb, {_i2.Hint? hint}) => + (super.noSuchMethod( + Invocation.method(#addBreadcrumb, [crumb], {#hint: hint}), returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override void bindClient(_i2.SentryClient? client) => super.noSuchMethod( - Invocation.method( - #bindClient, - [client], - ), + Invocation.method(#bindClient, [client]), returnValueForMissingStub: null, ); + @override _i2.Hub clone() => (super.noSuchMethod( - Invocation.method( - #clone, - [], - ), - returnValue: _FakeHub_11( - this, - Invocation.method( - #clone, - [], - ), - ), + Invocation.method(#clone, []), + returnValue: _FakeHub_11(this, Invocation.method(#clone, [])), ) as _i2.Hub); + @override _i4.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], - ), + Invocation.method(#close, []), returnValue: _i4.Future.value(), returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + @override _i4.FutureOr configureScope(_i2.ScopeCallback? callback) => - (super.noSuchMethod(Invocation.method( - #configureScope, - [callback], - )) as _i4.FutureOr); + (super.noSuchMethod(Invocation.method(#configureScope, [callback])) + as _i4.FutureOr); + @override _i2.ISentrySpan startTransaction( String? name, @@ -1530,10 +1250,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { (super.noSuchMethod( Invocation.method( #startTransaction, - [ - name, - operation, - ], + [name, operation], { #description: description, #startTimestamp: startTimestamp, @@ -1545,7 +1262,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #customSamplingContext: customSamplingContext, }, ), - returnValue: _i8.startTransactionShim( + returnValue: _i9.startTransactionShim( name, operation, description: description, @@ -1558,6 +1275,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { customSamplingContext: customSamplingContext, ), ) as _i2.ISentrySpan); + @override _i2.ISentrySpan startTransactionWithContext( _i2.SentryTransactionContext? transactionContext, { @@ -1600,26 +1318,31 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), ), ) as _i2.ISentrySpan); + @override _i4.Future<_i2.SentryId> captureTransaction( _i2.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, + _i2.Hint? hint, }) => (super.noSuchMethod( Invocation.method( #captureTransaction, [transaction], - {#traceContext: traceContext}, - ), - returnValue: _i4.Future<_i2.SentryId>.value(_FakeSentryId_9( - this, - Invocation.method( - #captureTransaction, - [transaction], - {#traceContext: traceContext}, + {#traceContext: traceContext, #hint: hint}, + ), + returnValue: _i4.Future<_i2.SentryId>.value( + _FakeSentryId_9( + this, + Invocation.method( + #captureTransaction, + [transaction], + {#traceContext: traceContext, #hint: hint}, + ), ), - )), + ), ) as _i4.Future<_i2.SentryId>); + @override void setSpanContext( dynamic throwable, @@ -1627,14 +1350,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { String? transaction, ) => super.noSuchMethod( - Invocation.method( - #setSpanContext, - [ - throwable, - span, - transaction, - ], - ), + Invocation.method(#setSpanContext, [throwable, span, transaction]), returnValueForMissingStub: null, ); } diff --git a/sqflite/test/sentry_batch_test.dart b/sqflite/test/sentry_batch_test.dart index 50dc469ab3..974b8e2c04 100644 --- a/sqflite/test/sentry_batch_test.dart +++ b/sqflite/test/sentry_batch_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library sqflite_test; +library; import 'package:sentry/sentry.dart'; import 'package:sentry_sqflite/sentry_sqflite.dart'; diff --git a/sqflite/test/sentry_database_test.dart b/sqflite/test/sentry_database_test.dart index b97f97784e..db59e9a940 100644 --- a/sqflite/test/sentry_database_test.dart +++ b/sqflite/test/sentry_database_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library sqflite_test; +library; import 'package:sentry/sentry.dart'; import 'package:sentry/src/sentry_tracer.dart'; diff --git a/sqflite/test/sentry_sqflite_database_factory_dart_test.dart b/sqflite/test/sentry_sqflite_database_factory_dart_test.dart index 38bc23d404..d25ae1144d 100644 --- a/sqflite/test/sentry_sqflite_database_factory_dart_test.dart +++ b/sqflite/test/sentry_sqflite_database_factory_dart_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library sqflite_test; +library; import 'package:sentry/sentry.dart'; import 'package:sentry/src/sentry_tracer.dart'; diff --git a/sqflite/test/sentry_sqflite_test.dart b/sqflite/test/sentry_sqflite_test.dart index f54cfda980..bae90f97d5 100644 --- a/sqflite/test/sentry_sqflite_test.dart +++ b/sqflite/test/sentry_sqflite_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library sqflite_test; +library; import 'package:sentry/sentry.dart'; import 'package:sentry_sqflite/sentry_sqflite.dart'; diff --git a/sqflite/test/version_test.dart b/sqflite/test/version_test.dart index 98e02ca499..01764f33f5 100644 --- a/sqflite/test/version_test.dart +++ b/sqflite/test/version_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library sqflite_test; +library; import 'dart:io';