diff --git a/test/ftp_test.dart b/test/ftp_test.dart index 9cf6ac2..0dd8ab8 100644 --- a/test/ftp_test.dart +++ b/test/ftp_test.dart @@ -270,8 +270,33 @@ void main() { } final sw = Stopwatch()..start(); + // 관리자 지시 (10/21): 전체 시험 부하에서만 가끔 실패 - 콘솔이 잘려도 남게, 실패하면 (시간 초과 포함) 시험 폴더 밖 + // %LOCALAPPDATA%\Temp\jj_ftp28_fail_<시각>.txt 에 시험 이름 · 옵션마다 걸린 시간 · 다른 점 · 목록을 쓴다. 성공하면 쓰지 않는다 + final progress = []; + var finished = false; + void writeFail(String why) { + final base = Platform.environment['LOCALAPPDATA']; + if (base == null || base.isEmpty) return; + final stamp = DateTime.now().toIso8601String().replaceAll(':', '').split('.').first; + try { + File(p.join(base, 'Temp', 'jj_ftp28_fail_$stamp.txt')).writeAsStringSync([ + 'ftp_test: FTP 맞추기 결과 = 실제 rsync 결과 (28 의 장면 · 옵션 28개)', + '까닭: $why · 걸린 시간 ${sw.elapsedMilliseconds}ms · 포트 $port · 끝 ${DateTime.now().toIso8601String()}', + '옵션마다:', + ...progress.map((x) => ' $x'), + '', + ...bad, + ].join('\n')); + } catch (_) {} + } + + // 시간 초과로 몸통이 끊겨도 (tearDown 은 돈다) 어디까지 갔는지 남긴다 + addTearDown(() { + if (!finished) writeFail('끝나지 않음 (시간 초과 · 예외)'); + }); for (final opts in sceneOptions) { final t0 = sw.elapsedMilliseconds; + progress.add('$opts - 시작 ${t0}ms'); writeScene(src, want); final w = await realRsyncTree(rsync, src, want, opts); final wantList = listing(want); @@ -300,7 +325,10 @@ void main() { listing(got), ].join('\n')); } + progress[progress.length - 1] += ' · ${sw.elapsedMilliseconds - t0}ms · ${d.isEmpty && error == null ? '같음' : '다름'}'; } + finished = true; + if (bad.isNotEmpty) writeFail('결과가 rsync 와 다름 ${bad.length}개'); expect(bad, isEmpty, reason: bad.join('\n')); }, skip: hasPy ? false : '시험용 파이썬 없음', timeout: const Timeout(Duration(minutes: 5)));