WIP 시험 흔들림: sftp_explorer_test 는 실제 시간으로 기다리고 시험 서버는 포트가 받는 것을 본 뒤 시작 (검토 대기)

관리자 지적 (10/18): "처음 연결: 지문 안내 → … → 지문은 설정에 저장" 이 전체 시험 (wt_mgr 00e9685) 에서만 실패.
시험 서버 (paramiko) 는 PORT 를 찍기 전에 listen 하므로, 무거울 때 걸리는 것은 settle 의 횟수 (300번 ≈ 10~15초) 였다 - 키 교환이 그보다 오래 걸림.
- settle: 횟수 대신 실제 시간 (처음 90초) 까지 조건을 기다린다.
- SftpTestServer.start: PORT · FINGERPRINT 줄을 기다리는 시간을 정하고 (60 · 30초, 서버가 죽으면 끝없이 기다리지 않게), 포트가 연결을 받는 것을 본 뒤 돌려준다.

시험: sftp_explorer · sftp_stream · sftp_test 10 통과.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sec_fix_b
RyuJongJin 2026-10-18 03:00:02 +09:00
parent 19d4f7bf3d
commit 38f53e70cc
2 changed files with 17 additions and 4 deletions

View File

@ -32,8 +32,10 @@ void main() {
} }
}); });
Future<void> settle(WidgetTester tester, bool Function() done, {int rounds = 300}) async { // 횟수가 아니라 실제 시간으로 기다린다 (전체 시험이 함께 돌아 무거우면 paramiko 서버의 키 교환이 몇십 초 걸린다 - 관리자 지적 10/18)
for (var i = 0; i < rounds; i++) { Future<void> settle(WidgetTester tester, bool Function() done, {Duration limit = const Duration(seconds: 90)}) async {
final end = DateTime.now().add(limit);
while (DateTime.now().isBefore(end)) {
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 30))); await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 30)));
await tester.pump(); await tester.pump();
if (done()) break; if (done()) break;

View File

@ -41,8 +41,19 @@ class SftpTestServer {
]); ]);
final lines = pr.stdout.transform(utf8.decoder).transform(const LineSplitter()).asBroadcastStream(); final lines = pr.stdout.transform(utf8.decoder).transform(const LineSplitter()).asBroadcastStream();
pr.stderr.drain<void>(); pr.stderr.drain<void>();
final port = int.parse((await lines.firstWhere((l) => l.startsWith('PORT '))).split(' ')[1]); final port = int.parse((await lines.firstWhere((l) => l.startsWith('PORT ')).timeout(const Duration(seconds: 60))).split(' ')[1]);
final fp = (await lines.firstWhere((l) => l.startsWith('FINGERPRINT '))).split(' ')[1]; final fp = (await lines.firstWhere((l) => l.startsWith('FINGERPRINT ')).timeout(const Duration(seconds: 30))).split(' ')[1];
// 무거울 때도 포트가 연결을 받는 것을 본 뒤에 시작한다 (관리자 지적 10/18)
final end = DateTime.now().add(const Duration(seconds: 30));
while (true) {
try {
(await Socket.connect('127.0.0.1', port, timeout: const Duration(seconds: 2))).destroy();
break;
} on SocketException {
if (DateTime.now().isAfter(end)) rethrow;
await Future<void>.delayed(const Duration(milliseconds: 200));
}
}
return SftpTestServer._(pr, port, fp); return SftpTestServer._(pr, port, fp);
} }