import 'package:flutter_test/flutter_test.dart'; import 'package:jj_mkvmaker/core/sync/copy_commands.dart'; import 'package:jj_mkvmaker/core/sync/copy_output.dart'; import 'package:jj_mkvmaker/core/sync/rsync_options.dart'; /// 나누기 sync_tools 약속 시험: lib/core/sync/ 모듈마다 맨 위 약속 (입력 · 출력 · 오류 없음). /// 실제 rsync · robocopy 실행은 rsync_msys_args_test · move_settled_test 등이 본다 void main() { test('rsync_options: 따옴표 · 굽은 따옴표 · 대시 고쳐 나누기 · 문제는 던지지 않고 목록으로', () { expect(splitOptions('-av --exclude="a b.txt"'), ['-av', '--exclude=a b.txt']); expect(splitOptions('–delete --exclude=‘*.log’'), ['--delete', '--exclude=*.log']); expect(optionProblems('-a "x', windows: false).first.kind, OptionProblemKind.unclosed); expect(optionProblems('-a delete', windows: false).map((e) => e.kind), [OptionProblemKind.path]); expect(optionProblems('--exclude-from=list.txt', windows: true).map((e) => e.kind), [OptionProblemKind.relativePath]); expect(optionProblems('-avP --exclude *.tmp', windows: false), isEmpty); expect(listFileValues(['--files-from', '/a/list', '-f', '. /b/rules']), ['/a/list', '/b/rules']); expect(optionProblemHint([const OptionProblem(OptionProblemKind.noValue, 'x')], windows: false), isNotEmpty); }); test('copy_commands: rsync 인수 (원본 지우기는 이동일 때만 · 경로는 MSYS 꼴) · robocopy 묶음 · 성공 코드', () { final a = rsyncArgs(options: '-av --remove-source-files', sources: [r'C:\s\dir\'], dest: r'D:\t', bandwidthKBps: 100); expect(a, ['-av', '--bwlimit=100', '--exclude=~jjren_*', '--exclude=~jjback_*', '/cygdrive/c/s/dir', '/cygdrive/d/t/']); expect(rsyncArgs(options: '-a', sources: ['/s'], dest: '/t', move: true, windows: false), contains('--remove-source-files')); expect(rsyncDestPath('//nas/share/x'), r'\\nas\share\x'); expect(withUpdateOption('-avu'), '-avu'); expect(withUpdateOption('-av'), '-av -u'); final runs = robocopyRuns(options: '/E', folders: [r'C:\s\f'], files: [r'C:\s\a.txt'], dest: r'D:\t', move: true); expect(runs.first.take(2), [r'C:\s\f', r'D:\t\f']); expect(runs.first, containsAll(['/MOVE', '/XJ'])); expect(runs.last, [r'C:\s', r'D:\t', 'a.txt', '/MOV', '/IS', '/IT', '/IM', '/XJ']); expect([rsyncOk(24), rsyncOk(23), robocopyOk(7), robocopyOk(8)], [true, false, true, false]); expect(CopyMethod.of('없음'), CopyMethod.builtin); }); test('copy_output: 줄 중간에서 끊긴 조각을 이어 읽음 · 진행률 · 속도 · 모르는 줄은 건너뜀', () { final r = RsyncOutput(); expect(r.feed('sending incremental file list\nsub/'), isEmpty); expect(r.feed('\nsub/inner.txt\n 1,024 45% 1.50MB/s 0:00:01 (xfr#1, to-chk=3/10)\r'), ['sub/inner.txt']); expect((r.currentPercent, r.checked, r.checkTotal), (0.45, 7, 10)); expect(r.currentSpeed, 1.5 * 1024 * 1024); final b = RobocopyOutput(); expect(b.feed('\t New File \t\t 1234\tC:\\s\\a.txt\n\t *EXTRA File \t\t 1\tx\n 50%\n'), ['C:\\s\\a.txt']); expect(b.currentPercent, 0.5); }); }