import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; import 'package:jj_mkvmaker/core/sync_preview.dart' show optionsUpdate; import 'package:jj_mkvmaker/core/sync_tools.dart'; import 'package:path/path.dart' as p; /// modular_sync #3 OptionText 약속: 옵션 글에 rsync 옵션이 있는지는 popt 규칙 하나 (rsyncHasOption) - 값 자리는 옵션으로 보지 않는다. /// 예전 -u 확인 세 곳은 "-로 시작하는 낱말에 u 가 있으면" 이라 -f'- build/' 의 u 를 -u 로 읽었다 (미리 보기는 "더 새것 건너뜀", 실제는 덮어씀) void main() { test('판단 표: 짧은 묶음 · 값을 받는 글자 뒤 · 값을 받는 옵션의 다음 낱말 · 긴 옵션 · = 값', () { bool u(String opts) => rsyncHasOption(splitOptions(opts), short: 'u', long: '--update'); expect([u('-avu'), u('-uav'), u('-a --update'), u('-a -u')], [true, true, true, true]); expect([u('-avHPOg'), u("-avf'- build/'"), u('-av -f "- run/"'), u('--exclude -u.txt -a'), u('--filter "- u*"'), u('--exclude=-u')], [false, false, false, false, false, false]); expect(u("-avf'- x' -u"), isTrue, reason: '값 뒤의 진짜 -u'); expect([optionsUpdate('-avu'), optionsUpdate("-avf'- build/'")], [true, false], reason: '미리 보기가 쓰는 판단도 같은 하나'); expect(withUpdateOption("-avf'- build/'"), "-avf'- build/' -u", reason: '⇄ 에서 -u 를 더할 때도 값의 u 를 -u 로 보지 않음'); }); test('실제 rsync: 받는 쪽이 더 새 파일 - 옵션 글마다 앱의 -u 판단과 rsync 가 보내는지가 맞음', () async { final rsync = p.join(Directory.current.path, 'third_party', 'rsync', 'windows', 'rsync.exe'); if (!Platform.isWindows || !File(rsync).existsSync()) return markTestSkipped('rsync 없음'); final tmp = Directory.systemTemp.createTempSync('jj_opttext_'); addTearDown(() => tmp.deleteSync(recursive: true)); final now = DateTime.now(); File(p.join(tmp.path, 's', 'build.txt')) ..createSync(recursive: true) ..writeAsStringSync('old') ..setLastModifiedSync(now.subtract(const Duration(hours: 1))); File(p.join(tmp.path, 'd', 'build.txt')) ..createSync(recursive: true) ..writeAsStringSync('NEW!') ..setLastModifiedSync(now); // 거르기 값에 u 가 든 경우 (- build/ · - run/) 가 예전에 -u 로 오인되던 것 (build.txt 는 거르지 않음) for (final opts in ['-av', '-avu', "-avf'- build/'", "-avuf'- build/'", '-av -f "- run/"']) { final args = rsyncArgs(options: opts, sources: [p.join(tmp.path, 's')], dest: p.join(tmp.path, 'd'), contents: true); final r = await Process.run(rsync, ['--dry-run', '--out-format=%n', ...args]); expect(r.exitCode, 0, reason: '$opts: ${r.stderr}'); final sends = '${r.stdout}'.split('\n').any((l) => l.trim() == 'build.txt'); expect(sends, !optionsUpdate(opts), reason: '$opts: rsync 가 보내면 -u 아님 (${r.stdout})'); } }); }