diff --git a/CHANGELOG.md b/CHANGELOG.md index ec337f2103..584ba4e54f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ - 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 @@ -28,8 +31,7 @@ - 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)) diff --git a/dart/lib/sentry.dart b/dart/lib/sentry.dart index 9d5d420d63..81915914ef 100644 --- a/dart/lib/sentry.dart +++ b/dart/lib/sentry.dart @@ -19,7 +19,7 @@ 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/platform_checker.dart'; +export 'src/runtime_checker.dart'; export 'src/protocol.dart'; export 'src/protocol/sentry_feedback.dart'; export 'src/protocol/sentry_proxy.dart'; diff --git a/dart/lib/src/environment/environment_variables.dart b/dart/lib/src/environment/environment_variables.dart index 7efbd877a6..51c8b1ea0d 100644 --- a/dart/lib/src/environment/environment_variables.dart +++ b/dart/lib/src/environment/environment_variables.dart @@ -1,4 +1,4 @@ -import '../platform_checker.dart'; +import '../runtime_checker.dart'; import '_io_environment_variables.dart' if (dart.library.js_interop) '_web_environment_variables.dart' as env; @@ -28,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/io_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart index 19e2ec5fac..21ef23d69f 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,7 +82,7 @@ class IoEnricherEventProcessor implements EnricherEventProcessor { } 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 c3dfd47c71..c16e90319e 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 @@ -89,7 +89,7 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { Map _getDartContext() { return { - 'compile_mode': _options.platformChecker.compileMode, + 'compile_mode': _options.runtimeChecker.compileMode, }; } 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/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 97c05815be..56325fa25b 100644 --- a/dart/lib/src/platform/_web_platform.dart +++ b/dart/lib/src/platform/_web_platform.dart @@ -2,40 +2,30 @@ 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 @@ -44,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 e3d5ae9f32..ea0ed3fdf7 100644 --- a/dart/lib/src/platform/platform.dart +++ b/dart/lib/src/platform/platform.dart @@ -1,41 +1,30 @@ -import 'dart:typed_data'; - import '_io_platform.dart' if (dart.library.js_interop) '_web_platform.dart' - as platform; - -const Platform instance = platform.instance; + as impl; -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/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/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 9660cd3255..d89d26c46c 100644 --- a/dart/lib/src/sentry.dart +++ b/dart/lib/src/sentry.dart @@ -87,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, @@ -123,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; } diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index 696ef49fab..20bbbd5c9a 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -67,9 +67,9 @@ class SentryClient { ); // 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) { @@ -214,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) { @@ -249,7 +249,7 @@ class SentryClient { SentryThread? sentryThread; - if (!_options.platformChecker.isWeb && + if (!_options.platform.isWeb && isolateName != null && _options.attachThreads) { sentryException = sentryException.copyWith(threadId: isolateId); diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 41fae90eaa..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'; @@ -271,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. @@ -494,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); } 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/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/test/event_processor/enricher/io_enricher_test.dart b/dart/test/event_processor/enricher/io_enricher_test.dart index 593e9afe99..38bb60e3e1 100644 --- a/dart/test/event_processor/enricher/io_enricher_test.dart +++ b/dart/test/event_processor/enricher/io_enricher_test.dart @@ -5,10 +5,10 @@ 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/web_enricher_test.dart b/dart/test/event_processor/enricher/web_enricher_test.dart index ae27ecc392..1c3639ec42 100644 --- a/dart/test/event_processor/enricher/web_enricher_test.dart +++ b/dart/test/event_processor/enricher/web_enricher_test.dart @@ -3,10 +3,10 @@ library; import 'package:sentry/sentry.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 @@ -200,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/example_web_compile_test.dart b/dart/test/example_web_compile_test.dart index 20e2509b6f..12906e2968 100644 --- a/dart/test/example_web_compile_test.dart +++ b/dart/test/example_web_compile_test.dart @@ -48,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/load_dart_debug_images_integration_test.dart b/dart/test/load_dart_debug_images_integration_test.dart index 4b1309607d..966dec2e69 100644 --- a/dart/test/load_dart_debug_images_integration_test.dart +++ b/dart/test/load_dart_debug_images_integration_test.dart @@ -5,11 +5,10 @@ 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/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/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 551cc51691..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'; @@ -1906,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(); @@ -1918,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(); @@ -1930,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(); @@ -1942,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(); @@ -1952,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(); @@ -1963,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(); @@ -2298,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_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_options_test.dart b/dart/test/sentry_options_test.dart index 9a8bfe5153..2179f2e5bd 100644 --- a/dart/test/sentry_options_test.dart +++ b/dart/test/sentry_options_test.dart @@ -98,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', () { diff --git a/dart/test/sentry_test.dart b/dart/test/sentry_test.dart index 2acc385ce3..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'; @@ -372,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( @@ -386,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( @@ -402,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( @@ -443,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; @@ -455,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) { @@ -468,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; @@ -480,7 +482,8 @@ 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) { @@ -505,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/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/file/lib/src/sentry_file_extension.dart b/file/lib/src/sentry_file_extension.dart index 2ddb327605..3436a3ad8f 100644 --- a/file/lib/src/sentry_file_extension.dart +++ b/file/lib/src/sentry_file_extension.dart @@ -30,8 +30,7 @@ extension SentryFileExtension on File { 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/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/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/lib/src/event_processor/flutter_enricher_event_processor.dart b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart index f34d7e28f0..dbadf223eb 100644 --- a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart +++ b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart @@ -19,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. @@ -40,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); @@ -206,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()) { diff --git a/flutter/lib/src/event_processor/screenshot_event_processor.dart b/flutter/lib/src/event_processor/screenshot_event_processor.dart index 2526a19db3..17de36b99a 100644 --- a/flutter/lib/src/event_processor/screenshot_event_processor.dart +++ b/flutter/lib/src/event_processor/screenshot_event_processor.dart @@ -92,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.', 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/web_sdk_integration.dart b/flutter/lib/src/integrations/web_sdk_integration.dart index 05d0d2e658..98ca504a49 100644 --- a/flutter/lib/src/integrations/web_sdk_integration.dart +++ b/flutter/lib/src/integrations/web_sdk_integration.dart @@ -33,7 +33,7 @@ class WebSdkIntegration implements Integration { _options = options; try { - final scripts = options.platformChecker.isDebugMode() + final scripts = options.runtimeChecker.isDebugMode() ? debugScripts : productionScripts; await _scriptLoader.loadWebSdk(scripts); diff --git a/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart b/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart index 6437d7d32e..a43a218156 100644 --- a/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart +++ b/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart @@ -18,7 +18,7 @@ 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 { 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/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/screenshot/recorder.dart b/flutter/lib/src/screenshot/recorder.dart index cea9e86391..363c16cfdd 100644 --- a/flutter/lib/src/screenshot/recorder.dart +++ b/flutter/lib/src/screenshot/recorder.dart @@ -35,7 +35,7 @@ class ScreenshotRecorder { privacyOptions ??= options.privacy; final maskingConfig = - privacyOptions.buildMaskingConfig(_log, options.platformChecker); + privacyOptions.buildMaskingConfig(_log, options.runtimeChecker); _maskingConfig = maskingConfig.length > 0 ? maskingConfig : null; } diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 2bf9de35c4..1af1e29f1d 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -64,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); } @@ -74,9 +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 isOnErrorSupported = !options.platformChecker.isWeb; + 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,13 +126,13 @@ mixin SentryFlutter { // Not all platforms have a native integration. if (_native != null) { if (_native!.supportsCaptureEnvelope) { - 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!)); } } @@ -141,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), ); @@ -159,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()); @@ -180,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)); } @@ -198,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()); } diff --git a/flutter/lib/src/sentry_flutter_options.dart b/flutter/lib/src/sentry_flutter_options.dart index 523c537a5d..4c9d8ea97e 100644 --- a/flutter/lib/src/sentry_flutter_options.dart +++ b/flutter/lib/src/sentry_flutter_options.dart @@ -18,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(); } @@ -331,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(); diff --git a/flutter/lib/src/sentry_privacy_options.dart b/flutter/lib/src/sentry_privacy_options.dart index 67fa90f637..138494571a 100644 --- a/flutter/lib/src/sentry_privacy_options.dart +++ b/flutter/lib/src/sentry_privacy_options.dart @@ -28,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(); @@ -73,7 +73,7 @@ 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); diff --git a/flutter/lib/src/view_hierarchy/view_hierarchy_integration.dart b/flutter/lib/src/view_hierarchy/view_hierarchy_integration.dart index 97afeed81a..c17d179cc1 100644 --- a/flutter/lib/src/view_hierarchy/view_hierarchy_integration.dart +++ b/flutter/lib/src/view_hierarchy/view_hierarchy_integration.dart @@ -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/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/pubspec.yaml b/flutter/pubspec.yaml index 3d003c604b..6f860dc79f 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -48,6 +48,7 @@ dev_dependencies: ref: 6aa2c2642f507eab3df83373189170797a9fa5e7 jnigen: 0.14.0 + platform: any flutter: plugin: platforms: 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 3a7e7462a2..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'; @@ -220,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()); @@ -252,7 +265,7 @@ void main() { .firstWhere((element) => element.name == 'Flutter'); expect(flutterRuntime?.name, 'Flutter'); - expect(flutterRuntime?.compiler, pair.value); + expect(flutterRuntime?.compiler, entry.compiler); } }); @@ -379,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) { @@ -415,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 d31e9fd36a..e21ba2379f 100644 --- a/flutter/test/event_processor/screenshot_event_processor_test.dart +++ b/flutter/test/event_processor/screenshot_event_processor_test.dart @@ -6,11 +6,12 @@ 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() { @@ -349,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/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 60759afdd4..02de4fb463 100644 --- a/flutter/test/integrations/init_native_sdk_test.dart +++ b/flutter/test/integrations/init_native_sdk_test.dart @@ -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/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/profiling_test.dart b/flutter/test/profiling_test.dart index fb0c4ce905..1091f893f1 100644 --- a/flutter/test/profiling_test.dart +++ b/flutter/test/profiling_test.dart @@ -5,9 +5,9 @@ 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/replay_native_test.dart b/flutter/test/replay/replay_native_test.dart index 9c10a3702b..b57e767d87 100644 --- a/flutter/test/replay/replay_native_test.dart +++ b/flutter/test/replay/replay_native_test.dart @@ -8,6 +8,7 @@ import 'dart:async'; 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 @@ -28,7 +29,7 @@ void main() { for (final mockPlatform in [ MockPlatform.android(), - MockPlatform.iOs(), + MockPlatform.iOS(), ]) { group('$SentryNativeBinding (${mockPlatform.operatingSystem})', () { late SentryNativeBinding sut; @@ -41,10 +42,12 @@ void main() { setUp(() { hub = MockHub(); native = NativeChannelFixture(); - options = - defaultTestOptions(MockPlatformChecker(mockPlatform: mockPlatform)) - ..methodChannel = native.channel - ..replay.quality = SentryReplayQuality.low; + + options = defaultTestOptions() + ..platform = mockPlatform + ..methodChannel = native.channel + ..replay.quality = SentryReplayQuality.low; + sut = createBinding(options); if (mockPlatform.isIOS) { 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/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 103e240b70..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'; @@ -73,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 { @@ -131,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( @@ -185,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( @@ -228,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 { @@ -275,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; @@ -324,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( @@ -369,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( @@ -396,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 @@ -439,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 @@ -482,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( @@ -531,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 = '' @@ -558,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 = ''; @@ -584,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 = ''; @@ -617,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) { @@ -638,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( @@ -703,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( @@ -758,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_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 b041e71105..37ac30cd3e 100644 --- a/flutter/test/sentry_native_channel_test.dart +++ b/flutter/test/sentry_native_channel_test.dart @@ -7,21 +7,21 @@ 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/min_version_test/pubspec.yaml b/min_version_test/pubspec.yaml index 49a693a6cb..40bcc4a009 100644 --- a/min_version_test/pubspec.yaml +++ b/min_version_test/pubspec.yaml @@ -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