Sumber yang diterbitkan
Muat turun ZIP sumber
CH-J SM Mobile
Layari direktori dan fail untuk keluaran aplikasi tertentu.
CH-J / SM Mobile
175 fail
sm-mobile-20261016T185235Z-8e93ecc1b59a
Ditambah: · Dibina:
1
import 'dart:async';2
import 'dart:io';3
import 'package:flutter_test/flutter_test.dart';4
import 'package:integration_test/integration_test.dart';5
import 'package:sm_mobile/services/net/icmp_probe.dart';7
/// Real ICMP from the device: Linux ping sockets on Android, Darwin ICMP8
/// datagram sockets on iOS. Loopback must always work. Extra targets9
/// (SM_ICMP_TARGETS, comma separated) are measured and printed; with10
/// SM_ICMP_EXPECT_ROUTERS=true at least one router must answer with Time11
/// Exceeded, which proves the traceroute error path on this platform.12
/// Results are also written to the app's temporary directory, because a13
/// wireless `flutter run` on iOS does not forward print output. The folder14
/// name makes the app delete it at the next launch or lock.15
final _report = File(16
'${Directory.systemTemp.path}/sm-transfer-devicetest/icmp.txt',17
);19
void _log(String line) {20
// ignore: avoid_print21
print(line);22
_report.parent.createSync(recursive: true);23
_report.writeAsStringSync('$line\n', mode: FileMode.append, flush: true);24
}26
void _test(String name, Future<void> Function(WidgetTester) body) =>27
testWidgets(name, (tester) async {28
try {29
await body(tester);30
_log('PASS $name');31
} catch (e) {32
_log('FAIL $name: $e');33
rethrow;34
}35
}, timeout: const Timeout(Duration(minutes: 10)));37
void main() {38
IntegrationTestWidgetsFlutterBinding.ensureInitialized();39
setUpAll(() {40
if (_report.existsSync()) _report.deleteSync();41
_log(42
'START ${Platform.operatingSystem} ${Platform.operatingSystemVersion}',43
);44
});45
const targets = String.fromEnvironment('SM_ICMP_TARGETS');46
const expectRouters = bool.fromEnvironment('SM_ICMP_EXPECT_ROUTERS');48
Future<List<ProbeEvent>> collect(IcmpRun run) =>49
run.events.toList().timeout(const Duration(minutes: 3));51
String show(ProbeEvent e) =>52
'${e.ttl}.${e.seq} ${e.status.name} ${e.from?.address ?? '*'} '53
'${e.rttMs?.toStringAsFixed(2) ?? ''}';55
_test('loopback ping (IPv4, IPv6), traceroute and cancel', (_) async {56
for (final target in [57
InternetAddress.loopbackIPv4,58
InternetAddress.loopbackIPv6,59
]) {60
final events = await collect(61
IcmpProbe.ping(62
target,63
const PingSettings(count: 3, interval: Duration(milliseconds: 300)),64
),65
);66
_log('ICMP ping $target: ${events.map(show).join(' | ')}');67
expect(events.map((e) => e.status), everyElement(ProbeStatus.reply));68
}69
final trace = await collect(70
IcmpProbe.traceroute(InternetAddress.loopbackIPv4, const TraceSettings()),71
);72
expect(73
trace.every((e) => e.ttl == 1 && e.status == ProbeStatus.reply),74
true,75
);76
final run = IcmpProbe.ping(77
InternetAddress.loopbackIPv4,78
const PingSettings(count: 100),79
);80
final first = Completer<void>(), done = Completer<void>();81
var count = 0;82
run.events.listen((_) {83
count++;84
if (!first.isCompleted) first.complete();85
}, onDone: done.complete);86
await first.future;87
await run.cancel();88
await done.future.timeout(const Duration(seconds: 2));89
final after = count;90
await Future<void>.delayed(const Duration(seconds: 2));91
expect(count, after, reason: 'nothing after cancel');92
});94
_test('UDP/TCP traceroute, TTL, DF and continuous ping on loopback', (95
_,96
) async {97
final udp = await collect(98
IcmpProbe.traceroute(99
InternetAddress.loopbackIPv4,100
const TraceSettings(method: TraceMethod.udp, probes: 2),101
),102
);103
_log('UDP loopback: ${udp.map(show).join(' | ')}');104
expect(udp.every((e) => e.note == 'portUnreachable'), true);105
if (IcmpProbe.unsupported(TraceMethod.tcp) == null) {106
final server = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);107
final tcp = await collect(108
IcmpProbe.traceroute(109
InternetAddress.loopbackIPv4,110
TraceSettings(method: TraceMethod.tcp, port: server.port, probes: 2),111
),112
);113
await server.close();114
_log('TCP loopback: ${tcp.map(show).join(' | ')}');115
expect(tcp.every((e) => e.note == 'tcpOpen'), true);116
}117
final ttl = await collect(118
IcmpProbe.ping(119
InternetAddress.loopbackIPv4,120
const PingSettings(count: 2, ttl: 5, dontFragment: true),121
),122
);123
expect(ttl.every((e) => e.status == ProbeStatus.reply), true);124
final run = IcmpProbe.ping(125
InternetAddress.loopbackIPv4,126
const PingSettings(count: 0, interval: Duration(milliseconds: 200)),127
);128
final got = <ProbeEvent>[];129
final done = Completer<void>();130
run.events.listen(got.add, onDone: done.complete);131
await Future<void>.delayed(const Duration(milliseconds: 1500));132
await run.cancel();133
await done.future.timeout(const Duration(seconds: 2));134
expect(got.length, greaterThanOrEqualTo(4));135
});137
_test('measurements to configured targets', (_) async {138
var routers = 0;139
for (final name in targets.split(',').where((t) => t.isNotEmpty)) {140
final address = InternetAddress(name);141
try {142
final ping = await collect(143
IcmpProbe.ping(address, const PingSettings(count: 3)),144
);145
final stats = PingStats.of(ping);146
_log(147
'ICMP ping $name: sent ${stats.sent} received ${stats.received} '148
'avg ${stats.avg?.toStringAsFixed(2)} ms',149
);150
final trace = await collect(151
IcmpProbe.traceroute(152
address,153
const TraceSettings(maxHops: 20, timeout: Duration(seconds: 1)),154
),155
);156
routers += trace157
.where((e) => e.status == ProbeStatus.timeExceeded)158
.length;159
// The other probe methods where the platform supports them.160
for (final method in [TraceMethod.udp, TraceMethod.tcp]) {161
final why = IcmpProbe.unsupported(method);162
if (why != null) {163
_log('$method $name: not supported here ($why)');164
continue;165
}166
final other = await collect(167
IcmpProbe.traceroute(168
address,169
TraceSettings(170
method: method,171
maxHops: 20,172
probes: 2,173
timeout: const Duration(seconds: 1),174
port: method == TraceMethod.tcp ? 443 : null,175
),176
),177
);178
routers += other179
.where((e) => e.status == ProbeStatus.timeExceeded)180
.length;181
_log('$method trace $name:\n${other.map(show).join('\n')}');182
expect(183
other.any((e) => e.status == ProbeStatus.reply),184
true,185
reason: '$method: destination reached',186
);187
}188
_log('ICMP trace $name:\n${trace.map(show).join('\n')}');189
} on IcmpUnavailable catch (e) {190
_log('ICMP $name unavailable: $e');191
rethrow;192
}193
}194
if (expectRouters) expect(routers, greaterThan(0));195
});196
}SHA-256
9bf1b2f81f2564cc76625e651cb4fc46ae89f5c1872774a5ce7b6d32972f8fe6CH-J Proprietary Software License 1.14 · Kod sumber disediakan di bawah CH-J Proprietary Software License 1.14. Ketersediaannya tidak mengubah terma lesen atau memberikan hak tambahan.
SHA-256 arkib
46e427a43e87af091004f36145590bda8fe90086dfb0f631afeb5029fb0b5655