diff --git a/test/ftp_test.dart b/test/ftp_test.dart index 1d0243d..a50dae4 100644 --- a/test/ftp_test.dart +++ b/test/ftp_test.dart @@ -236,7 +236,7 @@ void main() { }, skip: hasPy ? false : '시험용 파이썬 없음'); test('관리자 지시 (10/20): FTP 맞추기 결과 = 실제 rsync 결과 (28 의 장면 · 옵션 28개)', () async { - final rsync = bundledRsync; + final rsync = sceneRsync; if (rsync == null) return markTestSkipped('앱에 든 rsync 가 없음 (tool\\fetch_rsync.ps1)'); await start('plain'); FtpRegistry.configure([srv(security: 'none')]); diff --git a/test/sftp_test.dart b/test/sftp_test.dart index a2a8551..637be7f 100644 --- a/test/sftp_test.dart +++ b/test/sftp_test.dart @@ -211,7 +211,7 @@ void main() { }, skip: hasServer ? false : 'SFTP 시험 서버 (paramiko) 없음'); test('관리자 지시 (10/20): SFTP 맞추기 결과 = 실제 rsync 결과 (28 의 장면 · 옵션 28개)', () async { - final rsync = bundledRsync; + final rsync = sceneRsync; if (rsync == null) return markTestSkipped('앱에 든 rsync 가 없음 (tool\\fetch_rsync.ps1)'); await start(); SftpRegistry.configure([srv(fp: fingerprint)]); diff --git a/test/smb_test.dart b/test/smb_test.dart index 2765a5f..3d5eb4f 100644 --- a/test/smb_test.dart +++ b/test/smb_test.dart @@ -12,6 +12,7 @@ import 'package:path/path.dart' as p; import 'package:jj_mkvmaker/core/file_ops.dart'; import 'package:jj_mkvmaker/core/rsync_filter.dart'; import 'package:jj_mkvmaker/core/sync_preview.dart'; +import 'support/rsync_scenes.dart'; /// 88: Android SMB (smbj) 의 Dart 쪽 - 플랫폼 채널을 가짜 서버로 (실제 smbj · 서버 연결은 Android 기기 확인 몫) class _FakeSmb { @@ -263,4 +264,34 @@ void main() { expect(fake.files.containsKey(r'dst\old.txt'), isFalse); expect((fake.files.containsKey(r'dst\gone\g.tmp'), fake.files.containsKey(r'dst\gone\g.txt')), (true, false)); }); + test('관리자 지시 (10/20): SMB 맞추기 결과 = 실제 rsync 결과 (28 의 장면 · 옵션 28개, 가짜 채널)', () async { + final rsync = sceneRsync; + if (rsync == null) return markTestSkipped('앱에 든 rsync 가 없음 (tool\\fetch_rsync.ps1)'); + SmbRegistry.configure(const [server]); + final tmp = Directory.systemTemp.createTempSync('jj_smbscene_'); + addTearDown(() => tmp.deleteSync(recursive: true)); + final src = p.join(tmp.path, 'src'), want = p.join(tmp.path, 'rsync'), seed = p.join(tmp.path, 'seed'); + // 가짜 공유의 scene 폴더 → 트리 (treeOf 와 같은 모양) + Map fakeTree() => { + for (final e in fake.files.entries) + if (e.key.startsWith(r'scene\')) + e.key.substring(6).replaceAll(r'\', '/'): e.value == null ? '/' : utf8.decode(e.value!), + }; + final bad = []; + for (final opts in sceneOptions) { + writeScene(src, want); + final w = await realRsyncTree(rsync, src, want, opts); + writeScene(src, seed); + fake.files + ..clear() + ..['scene'] = null; + for (final e in treeOf(seed).entries) { + fake.files['scene\\${e.key.replaceAll('/', r'\')}'] = e.value == '/' ? null : utf8.encode(e.value); + } + await FileOps().mirror(src, 'smb://m1/scene', delete: optionsDelete(opts), filter: RsyncFilter.parse(opts)); + final d = treeDiff(w, fakeTree()); + if (d.isNotEmpty) bad.add('$opts\n ${d.join('\n ')}'); + } + expect(bad, isEmpty, reason: bad.join('\n')); + }); } diff --git a/test/support/rsync_scenes.dart b/test/support/rsync_scenes.dart index fae5ad7..a29c053 100644 --- a/test/support/rsync_scenes.dart +++ b/test/support/rsync_scenes.dart @@ -54,7 +54,7 @@ const sceneOptions = [ ]; /// 앱에 들어 있는 rsync (Windows). 없으면 null -String? get bundledRsync { +String? get sceneRsync { final f = p.join(Directory.current.path, 'third_party', 'rsync', 'windows', 'rsync.exe'); return Platform.isWindows && File(f).existsSync() ? f : null; } diff --git a/test/webdav_test.dart b/test/webdav_test.dart index 94d2134..048ecf0 100644 --- a/test/webdav_test.dart +++ b/test/webdav_test.dart @@ -16,6 +16,7 @@ import 'package:path/path.dart' as p; import 'support/dav_server.dart'; import 'package:jj_mkvmaker/core/sync_preview.dart'; import 'package:jj_mkvmaker/core/rsync_filter.dart'; +import 'support/rsync_scenes.dart'; void main() { late Directory tmp, remote, local; @@ -302,4 +303,19 @@ void main() { expect(Directory(real('cache')).existsSync(), isFalse); expect(Directory(real('gone')).existsSync(), isFalse); }); + test('관리자 지시 (10/20): WebDAV 맞추기 결과 = 실제 rsync 결과 (28 의 장면 · 옵션 28개)', () async { + final rsync = sceneRsync; + if (rsync == null) return markTestSkipped('앱에 든 rsync 가 없음 (tool\\fetch_rsync.ps1)'); + final src = p.join(local.path, 'scene_src'), want = p.join(local.path, 'scene_rsync'), got = p.join(remote.path, 'scene'); + final bad = []; + for (final opts in sceneOptions) { + writeScene(src, want); + final w = await realRsyncTree(rsync, src, want, opts); + writeScene(src, got); + await FileOps().mirror(src, 'dav://$id/scene', delete: optionsDelete(opts), filter: RsyncFilter.parse(opts)); + final d = treeDiff(w, treeOf(got)); + if (d.isNotEmpty) bad.add('$opts\n ${d.join('\n ')}'); + } + expect(bad, isEmpty, reason: bad.join('\n')); + }, timeout: const Timeout(Duration(minutes: 5))); }