|
1 |
| -@TestOn('vm') |
2 |
| -// ignore_for_file: invalid_use_of_internal_member |
3 |
| -library; |
4 |
| - |
5 |
| -import 'dart:isolate'; |
6 |
| -import 'dart:typed_data'; |
7 |
| - |
8 |
| -import 'package:flutter_test/flutter_test.dart'; |
9 |
| -import 'package:sentry_flutter/sentry_flutter.dart'; |
10 |
| -import 'package:sentry_flutter/src/native/java/android_envelope_sender.dart'; |
11 |
| -import 'package:sentry_flutter/src/isolate/isolate_worker.dart'; |
12 |
| - |
13 |
| -void main() { |
14 |
| - group('AndroidEnvelopeSender host behavior', () { |
15 |
| - test('warns and drops when not started', () { |
16 |
| - final options = SentryFlutterOptions(); |
17 |
| - options.debug = true; |
18 |
| - options.diagnosticLevel = SentryLevel.debug; |
19 |
| - final logs = <(SentryLevel, String)>[]; |
20 |
| - options.log = (level, message, {logger, exception, stackTrace}) { |
21 |
| - logs.add((level, message)); |
22 |
| - }; |
23 |
| - |
24 |
| - final sender = AndroidEnvelopeSender(options); |
25 |
| - sender.captureEnvelope(Uint8List.fromList([1, 2, 3]), false); |
26 |
| - |
27 |
| - expect( |
28 |
| - logs.any((e) => |
29 |
| - e.$1 == SentryLevel.warning && |
30 |
| - e.$2.contains( |
31 |
| - 'captureEnvelope called before worker started; dropping')), |
32 |
| - isTrue, |
33 |
| - ); |
34 |
| - }); |
35 |
| - |
36 |
| - test('close is a no-op when not started', () { |
37 |
| - final options = SentryFlutterOptions(); |
38 |
| - final sender = AndroidEnvelopeSender(options); |
39 |
| - expect(() => sender.close(), returnsNormally); |
40 |
| - expect(() => sender.close(), returnsNormally); |
41 |
| - }); |
42 |
| - |
43 |
| - test('warns and drops after close', () async { |
44 |
| - final options = SentryFlutterOptions(); |
45 |
| - options.debug = true; |
46 |
| - options.diagnosticLevel = SentryLevel.debug; |
47 |
| - final logs = <(SentryLevel, String)>[]; |
48 |
| - options.log = (level, message, {logger, exception, stackTrace}) { |
49 |
| - logs.add((level, message)); |
50 |
| - }; |
51 |
| - |
52 |
| - final sender = AndroidEnvelopeSender(options); |
53 |
| - await sender.start(); |
54 |
| - sender.close(); |
55 |
| - |
56 |
| - sender.captureEnvelope(Uint8List.fromList([9]), false); |
57 |
| - |
58 |
| - expect( |
59 |
| - logs.any((e) => |
60 |
| - e.$1 == SentryLevel.warning && |
61 |
| - e.$2.contains( |
62 |
| - 'captureEnvelope called before worker started; dropping')), |
63 |
| - isTrue, |
64 |
| - ); |
65 |
| - }); |
66 |
| - |
67 |
| - test('start is a no-op when already started', () async { |
68 |
| - final options = SentryFlutterOptions(); |
69 |
| - options.debug = true; |
70 |
| - options.diagnosticLevel = SentryLevel.debug; |
71 |
| - |
72 |
| - var spawnCount = 0; |
73 |
| - Future<Worker> fakeSpawn(WorkerConfig config, WorkerEntry entry) async { |
74 |
| - spawnCount++; |
75 |
| - final inbox = ReceivePort(); |
76 |
| - addTearDown(() => inbox.close()); |
77 |
| - final replies = ReceivePort(); |
78 |
| - return Worker(inbox.sendPort, replies); |
79 |
| - } |
80 |
| - |
81 |
| - final sender = AndroidEnvelopeSender(options, spawn: fakeSpawn); |
82 |
| - |
83 |
| - await sender.start(); |
84 |
| - await sender.start(); |
85 |
| - expect(spawnCount, 1); |
86 |
| - |
87 |
| - sender.close(); |
88 |
| - spawnCount = 0; |
89 |
| - |
90 |
| - await sender.start(); |
91 |
| - expect(spawnCount, 1); |
92 |
| - |
93 |
| - // Close twice should be safe. |
94 |
| - expect(() => sender.close(), returnsNormally); |
95 |
| - expect(() => sender.close(), returnsNormally); |
96 |
| - }); |
97 |
| - |
98 |
| - test('delivers tuple to worker after start', () async { |
99 |
| - final options = SentryFlutterOptions(); |
100 |
| - options.debug = true; |
101 |
| - options.diagnosticLevel = SentryLevel.debug; |
102 |
| - |
103 |
| - final inboxes = <ReceivePort>[]; |
104 |
| - Future<Worker> fakeSpawn(WorkerConfig config, WorkerEntry entry) async { |
105 |
| - final inbox = ReceivePort(); |
106 |
| - inboxes.add(inbox); |
107 |
| - addTearDown(() => inbox.close()); |
108 |
| - final replies = ReceivePort(); |
109 |
| - return Worker(inbox.sendPort, replies); |
110 |
| - } |
111 |
| - |
112 |
| - final sender = AndroidEnvelopeSender(options, spawn: fakeSpawn); |
113 |
| - await sender.start(); |
114 |
| - |
115 |
| - final payload = Uint8List.fromList([4, 5, 6]); |
116 |
| - sender.captureEnvelope(payload, true); |
117 |
| - |
118 |
| - final msg = await inboxes.last.first; |
119 |
| - expect(msg, isA<(TransferableTypedData, bool)>()); |
120 |
| - final (transferable, containsUnhandled) = |
121 |
| - msg as (TransferableTypedData, bool); |
122 |
| - expect(containsUnhandled, true); |
123 |
| - final data = transferable.materialize().asUint8List(); |
124 |
| - expect(data, [4, 5, 6]); |
125 |
| - |
126 |
| - sender.close(); |
127 |
| - }); |
128 |
| - |
129 |
| - test('uses expected WorkerConfig', () async { |
130 |
| - final options = SentryFlutterOptions(); |
131 |
| - options.debug = true; |
132 |
| - options.diagnosticLevel = SentryLevel.debug; |
133 |
| - |
134 |
| - WorkerConfig? seenConfig; |
135 |
| - Future<Worker> fakeSpawn(WorkerConfig config, WorkerEntry entry) async { |
136 |
| - seenConfig = config; |
137 |
| - final inbox = ReceivePort(); |
138 |
| - addTearDown(() => inbox.close()); |
139 |
| - final replies = ReceivePort(); |
140 |
| - return Worker(inbox.sendPort, replies); |
141 |
| - } |
142 |
| - |
143 |
| - final sender = AndroidEnvelopeSender(options, spawn: fakeSpawn); |
144 |
| - await sender.start(); |
145 |
| - |
146 |
| - expect(seenConfig, isNotNull); |
147 |
| - expect(seenConfig!.debugName, 'SentryAndroidEnvelopeSender'); |
148 |
| - expect(seenConfig!.debug, options.debug); |
149 |
| - expect(seenConfig!.diagnosticLevel, options.diagnosticLevel); |
150 |
| - |
151 |
| - sender.close(); |
152 |
| - }); |
153 |
| - |
154 |
| - test('sends are delivered sequentially with flags', () async { |
155 |
| - final options = SentryFlutterOptions(); |
156 |
| - options.debug = true; |
157 |
| - options.diagnosticLevel = SentryLevel.debug; |
158 |
| - |
159 |
| - final inboxes = <ReceivePort>[]; |
160 |
| - Future<Worker> fakeSpawn(WorkerConfig config, WorkerEntry entry) async { |
161 |
| - final inbox = ReceivePort(); |
162 |
| - inboxes.add(inbox); |
163 |
| - addTearDown(() => inbox.close()); |
164 |
| - final replies = ReceivePort(); |
165 |
| - return Worker(inbox.sendPort, replies); |
166 |
| - } |
167 |
| - |
168 |
| - final sender = AndroidEnvelopeSender(options, spawn: fakeSpawn); |
169 |
| - await sender.start(); |
170 |
| - |
171 |
| - sender.captureEnvelope(Uint8List.fromList([10]), true); |
172 |
| - sender.captureEnvelope(Uint8List.fromList([11]), false); |
173 |
| - |
174 |
| - final inbox = inboxes.last; |
175 |
| - final msgs = await inbox.take(2).toList(); |
176 |
| - final msg1 = msgs[0]; |
177 |
| - final msg2 = msgs[1]; |
178 |
| - |
179 |
| - expect(msg1, isA<(TransferableTypedData, bool)>()); |
180 |
| - expect(msg2, isA<(TransferableTypedData, bool)>()); |
181 |
| - |
182 |
| - final (t1, f1) = msg1 as (TransferableTypedData, bool); |
183 |
| - final (t2, f2) = msg2 as (TransferableTypedData, bool); |
184 |
| - expect(f1, true); |
185 |
| - expect(f2, false); |
186 |
| - final data1 = t1.materialize().asUint8List(); |
187 |
| - final data2 = t2.materialize().asUint8List(); |
188 |
| - expect(data1, [10]); |
189 |
| - expect(data2, [11]); |
190 |
| - |
191 |
| - sender.close(); |
192 |
| - }); |
193 |
| - }); |
194 |
| -} |
| 1 | +export 'android_envelope_sender_test_real.dart' |
| 2 | + if (dart.library.js_interop) 'android_envelope_sender_test_web.dart'; |
0 commit comments