frindlymap/test/discovery_test.dart

104 lines
3.5 KiB
Dart

import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:friendly_map/modules/discovery/discovery.dart';
import 'package:friendly_map/modules/platform/platform.dart';
class _FakeLan implements LanDiscovery {
final StreamController<LanPeer> ctl = StreamController<LanPeer>.broadcast(sync: true);
String? advertised;
bool started = false;
@override
Future<void> advertise({required String phone, required int port}) async => advertised = '$phone:$port';
@override
Stream<LanPeer> get peers => ctl.stream;
@override
Future<void> start() async => started = true;
@override
Future<void> stop() async => started = false;
}
void main() {
group('QR', () {
test('담았다가 읽으면 같다 (한글·특수문자 포함)', () {
const p = QrPayload(phone: '+821011112222', name: '정민호 😀', publicKey: 'a+b/c==');
final back = QrPayload.decode(p.encode())!;
expect(back.phone, p.phone);
expect(back.name, p.name);
expect(back.publicKey, p.publicKey);
});
test('우리 앱 QR 이 아니거나 깨졌으면 null', () {
expect(QrPayload.decode('https://example.com'), null);
expect(QrPayload.decode('fm1:@@@'), null);
expect(QrPayload.decode('fm1:'), null);
expect(QrPayload.decode(''), null);
});
});
group('흔들기', () {
test('짧은 시간에 세 번 세게 흔들면 한 번 알림', () {
final d = ShakeDetector();
var fired = 0;
var t = 0;
for (var i = 0; i < 3; i++) {
if (d.feed(25, t)) fired++;
t += 100;
if (d.feed(9.8, t)) fired++;
t += 100;
}
expect(fired, 1);
});
test('가만히 있거나 한 번만 움직이면 알리지 않음', () {
final d = ShakeDetector();
for (var t = 0; t < 3000; t += 50) {
expect(d.feed(9.8, t), false);
}
expect(d.feed(30, 3100), false);
});
test('느리게 세 번이면 알리지 않고, 알린 뒤 바로 또 알리지 않음', () {
final d = ShakeDetector();
var t = 0;
var fired = false;
for (var i = 0; i < 3; i++) {
fired = d.feed(25, t) || fired;
d.feed(9.8, t + 50);
t += 1500;
}
expect(fired, false);
final e = ShakeDetector();
var n = 0;
for (var i = 0; i < 12; i++) {
if (e.feed(25, i * 100)) n++;
e.feed(9.8, i * 100 + 50);
}
expect(n, 1);
});
});
group('같은 네트워크 주소록', () {
test('발견한 상대를 번호로 찾고, 나 자신은 제외, 주소가 바뀌면 다시 알림', () async {
final lan = _FakeLan();
final dir = LanDirectory(lan);
final seen = <LanPeer>[];
dir.seen.listen(seen.add);
await dir.start(myPhone: '+821011112222', myPort: 4000);
expect(lan.advertised, '+821011112222:4000');
expect(lan.started, true);
lan.ctl.add(const LanPeer(phone: '+821011112222', host: '10.0.0.1', port: 4000));
lan.ctl.add(const LanPeer(phone: '+821022223333', host: '10.0.0.2', port: 4001));
lan.ctl.add(const LanPeer(phone: '+821022223333', host: '10.0.0.2', port: 4001));
lan.ctl.add(const LanPeer(phone: '+821022223333', host: '10.0.0.9', port: 4001));
expect(seen.length, 2);
expect(dir.find('+821022223333')!.host, '10.0.0.9');
expect(dir.find('+821011112222'), null);
dir.forget('+821022223333');
expect(dir.all, isEmpty);
await dir.stop();
expect(lan.started, false);
});
});
}