Skip to content

Commit

Permalink
Normalize setContexts & setExtra
Browse files Browse the repository at this point in the history
  • Loading branch information
denrase committed Aug 14, 2023
1 parent 9709c72 commit a905fd1
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 107 deletions.
46 changes: 20 additions & 26 deletions flutter/lib/src/method_channel_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,33 @@ import 'package:meta/meta.dart';
/// Makes sure no invalid data is sent over method channels.
@internal
class MethodChannelHelper {
static dynamic normalize(dynamic data) {
if (data == null) {
return null;
}
if (_isPrimitive(data)) {
return data;
} else if (data is List<dynamic>) {
return _normalizeList(data);
} else if (data is Map<String, dynamic>) {
return normalizeMap(data);
} else {
return data.toString();
}
}

static Map<String, dynamic>? normalizeMap(Map<String, dynamic>? data) {
if (data == null) {
return null;
}
final mapToReturn = <String, dynamic>{};
data.forEach((key, value) {
if (_isPrimitive(value)) {
mapToReturn[key] = value;
} else if (value is List<dynamic>) {
mapToReturn[key] = _normalizeList(value);
} else if (value is Map<String, dynamic>) {
mapToReturn[key] = normalizeMap(value);
} else {
mapToReturn[key] = value.toString();
}
});
return mapToReturn;
return data.map((key, value) => MapEntry(key, normalize(value)));
}

static List<dynamic> _normalizeList(List<dynamic> data) {
final listToReturn = <dynamic>[];
for (final element in data) {
if (_isPrimitive(element)) {
listToReturn.add(element);
} else if (element is List<dynamic>) {
listToReturn.add(_normalizeList(element));
} else if (element is Map<String, dynamic>) {
listToReturn.add(normalizeMap(element));
} else {
listToReturn.add(element.toString());
}
static List<dynamic>? _normalizeList(List<dynamic>? data) {
if (data == null) {
return null;
}
return listToReturn;
return data.map((e) => normalize(e)).toList();
}

static bool _isPrimitive(dynamic value) {
Expand Down
14 changes: 11 additions & 3 deletions flutter/lib/src/sentry_native_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ class SentryNativeChannel {

Future<void> setContexts(String key, dynamic value) async {
try {
await _channel.invokeMethod('setContexts', {'key': key, 'value': value});
final normalizedValue = MethodChannelHelper.normalize(value);
await _channel.invokeMethod(
'setContexts',
{'key': key, 'value': normalizedValue},
);
} catch (error, stackTrace) {
_logError('setContexts', error, stackTrace);
}
Expand All @@ -100,7 +104,11 @@ class SentryNativeChannel {

Future<void> setExtra(String key, dynamic value) async {
try {
await _channel.invokeMethod('setExtra', {'key': key, 'value': value});
final normalizedValue = MethodChannelHelper.normalize(value);
await _channel.invokeMethod(
'setExtra',
{'key': key, 'value': normalizedValue},
);
} catch (error, stackTrace) {
_logError('setExtra', error, stackTrace);
}
Expand All @@ -114,7 +122,7 @@ class SentryNativeChannel {
}
}

Future<void> setTag(String key, dynamic value) async {
Future<void> setTag(String key, String value) async {
try {
await _channel.invokeMethod('setTag', {'key': key, 'value': value});
} catch (error, stackTrace) {
Expand Down
204 changes: 132 additions & 72 deletions flutter/test/method_channel_helper_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,91 +3,151 @@ import 'package:sentry_flutter/src/method_channel_helper.dart';
import 'package:collection/collection.dart';

void main() {
test('primitives', () {
var expected = <String, dynamic>{
'null': null,
'int': 1,
'float': 1.1,
'bool': true,
'string': 'Foo',
};

var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});
group('normalize', () {
test('primitives', () {
var expected = <String, dynamic>{
'null': null,
'int': 1,
'float': 1.1,
'bool': true,
'string': 'Foo',
};

var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);

expect(MethodChannelHelper.normalize(null), null);
expect(MethodChannelHelper.normalize(1), 1);
expect(MethodChannelHelper.normalize(1.1), 1.1);
expect(MethodChannelHelper.normalize(true), true);
expect(MethodChannelHelper.normalize('Foo'), 'Foo');
});

test('object', () {
expect(MethodChannelHelper.normalize(_CustomObject()), 'CustomObject()');
});

test('object in list', () {
var input = <String, dynamic>{
'object': [_CustomObject()]
};
var expected = <String, dynamic>{
'object': ['CustomObject()']
};

var actual = MethodChannelHelper.normalize(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('list with primitives', () {
var expected = <String, dynamic>{
'list': [null, 1, 1.1, true, 'Foo'],
};
test('object in map', () {
var input = <String, dynamic>{
'object': <String, dynamic>{'object': _CustomObject()}
};
var expected = <String, dynamic>{
'object': <String, dynamic>{'object': 'CustomObject()'}
};

var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
var actual = MethodChannelHelper.normalize(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});
});

test('map with primitives', () {
var expected = <String, dynamic>{
'map': <String, dynamic>{
group('normalizeMap', () {
test('primitives', () {
var expected = <String, dynamic>{
'null': null,
'int': 1,
'float': 1.1,
'bool': true,
'string': 'Foo',
},
};

var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});
};

test('object', () {
var input = <String, dynamic>{'object': _CustomObject()};
var expected = <String, dynamic>{'object': 'CustomObject()'};
var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

var actual = MethodChannelHelper.normalizeMap(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});
test('list with primitives', () {
var expected = <String, dynamic>{
'list': [null, 1, 1.1, true, 'Foo'],
};

test('object in list', () {
var input = <String, dynamic>{
'object': [_CustomObject()]
};
var expected = <String, dynamic>{
'object': ['CustomObject()']
};

var actual = MethodChannelHelper.normalizeMap(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});
var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('map with primitives', () {
var expected = <String, dynamic>{
'map': <String, dynamic>{
'null': null,
'int': 1,
'float': 1.1,
'bool': true,
'string': 'Foo',
},
};

var actual = MethodChannelHelper.normalizeMap(expected);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('object', () {
var input = <String, dynamic>{'object': _CustomObject()};
var expected = <String, dynamic>{'object': 'CustomObject()'};

var actual = MethodChannelHelper.normalizeMap(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('object in list', () {
var input = <String, dynamic>{
'object': [_CustomObject()]
};
var expected = <String, dynamic>{
'object': ['CustomObject()']
};

var actual = MethodChannelHelper.normalizeMap(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});

test('object in map', () {
var input = <String, dynamic>{
'object': <String, dynamic>{'object': _CustomObject()}
};
var expected = <String, dynamic>{
'object': <String, dynamic>{'object': 'CustomObject()'}
};

test('object in map', () {
var input = <String, dynamic>{
'object': <String, dynamic>{'object': _CustomObject()}
};
var expected = <String, dynamic>{
'object': <String, dynamic>{'object': 'CustomObject()'}
};

var actual = MethodChannelHelper.normalizeMap(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
var actual = MethodChannelHelper.normalizeMap(input);
expect(
DeepCollectionEquality().equals(actual, expected),
true,
);
});
});
}

Expand Down
16 changes: 10 additions & 6 deletions flutter/test/sentry_native_channel_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,17 @@ void main() {
});

test('setContexts', () async {
final value = {'object': Object()};
final normalizedValue = MethodChannelHelper.normalize(value);
when(fixture.methodChannel.invokeMethod(
'setContexts', {'key': 'fixture-key', 'value': 'fixture-value'}))
'setContexts', {'key': 'fixture-key', 'value': normalizedValue}))
.thenAnswer((_) => Future.value());

final sut = fixture.getSut();
await sut.setContexts('fixture-key', 'fixture-value');
await sut.setContexts('fixture-key', value);

verify(fixture.methodChannel.invokeMethod(
'setContexts', {'key': 'fixture-key', 'value': 'fixture-value'}));
'setContexts', {'key': 'fixture-key', 'value': normalizedValue}));
});

test('removeContexts', () async {
Expand All @@ -136,15 +138,17 @@ void main() {
});

test('setExtra', () async {
final value = {'object': Object()};
final normalizedValue = MethodChannelHelper.normalize(value);
when(fixture.methodChannel.invokeMethod(
'setExtra', {'key': 'fixture-key', 'value': 'fixture-value'}))
'setExtra', {'key': 'fixture-key', 'value': normalizedValue}))
.thenAnswer((_) => Future.value());

final sut = fixture.getSut();
await sut.setExtra('fixture-key', 'fixture-value');
await sut.setExtra('fixture-key', value);

verify(fixture.methodChannel.invokeMethod(
'setExtra', {'key': 'fixture-key', 'value': 'fixture-value'}));
'setExtra', {'key': 'fixture-key', 'value': normalizedValue}));
});

test('removeExtra', () async {
Expand Down

0 comments on commit a905fd1

Please sign in to comment.