144 lines
6.8 KiB
Dart
144 lines
6.8 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:jj_mkvmaker/app/transfer_job.dart';
|
|
import 'package:jj_mkvmaker/core/webdav.dart';
|
|
import 'package:path/path.dart' as p;
|
|
|
|
import 'support/dav_server.dart';
|
|
|
|
/// 214: 앱이 직접 하는 "안의 것" 이동 (WebDAV 가 낄 때 · 현재 방식) 은 대상에 맞춘 원본 파일만 지운다.
|
|
/// 예전에는 맞춘 뒤 원본 폴더를 다시 읽어 모든 파일을 지웠다 (건너뛴 것 · 도중에 생긴 것 · 링크 너머까지).
|
|
void main() {
|
|
late Directory tmp;
|
|
late String src, dst;
|
|
|
|
setUp(() {
|
|
tmp = Directory.systemTemp.createTempSync('jj_move_settled_');
|
|
src = p.join(tmp.path, 'src');
|
|
dst = p.join(tmp.path, 'dst');
|
|
File(p.join(src, 'a.txt'))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('a');
|
|
Directory(dst).createSync();
|
|
});
|
|
tearDown(() {
|
|
if (tmp.existsSync()) tmp.deleteSync(recursive: true);
|
|
});
|
|
|
|
TransferJob moveJob({String options = ''}) =>
|
|
TransferJob(sources: [src], dest: dst, move: true, contents: true, options: options);
|
|
|
|
test('214 a: -u 로 건너뛴 파일 (대상이 더 새것) 은 원본에 남는다 (rsync 처럼)', () async {
|
|
final old = File(p.join(src, 'keep.txt'))..writeAsStringSync('old source');
|
|
old.setLastModifiedSync(DateTime(2020));
|
|
File(p.join(dst, 'keep.txt')).writeAsStringSync('newer target');
|
|
final job = moveJob(options: '-u');
|
|
await job.run();
|
|
expect(job.error, isNull);
|
|
expect(File(p.join(dst, 'a.txt')).readAsStringSync(), 'a');
|
|
expect(File(p.join(src, 'a.txt')).existsSync(), isFalse, reason: '맞춘 것은 지움');
|
|
expect(old.existsSync(), isTrue, reason: '건너뛴 것은 남김 (예전에는 지웠다)');
|
|
expect(File(p.join(dst, 'keep.txt')).readAsStringSync(), 'newer target');
|
|
// 216 · 212: 원본에 남은 것을 다시 세어 끝 알림에
|
|
expect(job.leftInSource, 1);
|
|
expect(job.doneSummary(), contains('이동 끝: 1개 · src → dst'));
|
|
expect(job.doneSummary(), contains('1개는 원본에 남음 (건너뜀)'));
|
|
});
|
|
|
|
test('214 c: 맞추는 동안 원본에 새로 생긴 파일은 지우지 않는다', () async {
|
|
// 천천히 보내는 큰 파일 (맞추는 동안 새 파일을 만든다)
|
|
File(p.join(src, 'big.bin')).writeAsBytesSync(List.filled(300 * 1024, 7));
|
|
final job = TransferJob(sources: [src], dest: dst, move: true, contents: true, bandwidthKBps: 400);
|
|
final running = job.run();
|
|
await Future<void>.delayed(const Duration(milliseconds: 250));
|
|
File(p.join(src, 'arrived.txt')).writeAsStringSync('new');
|
|
await running;
|
|
expect(job.error, isNull);
|
|
expect(File(p.join(dst, 'big.bin')).lengthSync(), 300 * 1024);
|
|
expect(File(p.join(src, 'big.bin')).existsSync(), isFalse);
|
|
expect(File(p.join(src, 'arrived.txt')).existsSync(), isTrue, reason: '복사하지 않은 것은 남김');
|
|
});
|
|
|
|
test('214 d: 원본 안의 링크 (junction) 는 따라가지 않는다 - 링크가 가리키는 바깥 폴더의 파일은 그대로', () async {
|
|
final outside = Directory(p.join(tmp.path, 'outside'))..createSync();
|
|
final precious = File(p.join(outside.path, 'precious.txt'))..writeAsStringSync('keep me');
|
|
try {
|
|
Link(p.join(src, 'jn')).createSync(outside.path);
|
|
} on FileSystemException {
|
|
markTestSkipped('이 환경에서는 링크를 만들 수 없음');
|
|
return;
|
|
}
|
|
final job = moveJob();
|
|
await job.run();
|
|
expect(job.error, isNull);
|
|
expect(precious.existsSync(), isTrue);
|
|
expect(precious.readAsStringSync(), 'keep me');
|
|
expect(File(p.join(src, 'a.txt')).existsSync(), isFalse);
|
|
});
|
|
|
|
test('215: rsync 가 원본을 못 지우면 쉬운 말 + 오류 줄 (끝쪽) 을 보인다 - 전송한 파일 이름만 보이지 않게', () {
|
|
final out = [for (var i = 0; i < 15; i++) 'movie$i.mkv'];
|
|
final err = [
|
|
'sender failed to remove movie3.mkv: Permission denied (13)',
|
|
'sender failed to remove movie4.mkv: Permission denied (13)',
|
|
'rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1338) [sender=3.4.1]',
|
|
];
|
|
final text = rsyncFailureText(23, err, [...out, ...err]);
|
|
expect(text, startsWith('원본 파일을 지우지 못했습니다'));
|
|
expect(text, contains('rsync 종료 코드 23'));
|
|
expect(text, contains('Permission denied'));
|
|
expect(text, contains('(code 23)'));
|
|
expect(text, isNot(contains('movie10.mkv')), reason: '전송한 파일 이름 줄이 아니라 오류 줄');
|
|
// 원본 지우기와 상관없는 실패는 그 말을 붙이지 않는다
|
|
expect(rsyncFailureText(12, ['rsync error: error in rsync protocol data stream (code 12)'], const []), isNot(contains('원본 파일을 지우지')));
|
|
});
|
|
|
|
group('214 b: WebDAV', () {
|
|
late Directory remote;
|
|
late TestDavServer server;
|
|
setUp(() async {
|
|
remote = Directory(p.join(tmp.path, 'remote'))..createSync();
|
|
server = TestDavServer(remote);
|
|
await server.start();
|
|
final s = DavServer(id: 'nas', name: 'NAS', url: server.url, user: 'user', password: 'pass');
|
|
DavRegistry.configure([s]);
|
|
});
|
|
tearDown(() async {
|
|
DavRegistry.configure([]);
|
|
await server.stop();
|
|
});
|
|
|
|
test('214 b: 크기만 같고 내용이 다른 대상 (대상이 더 새것) 이 있어도, 이동은 다시 보내고 지운다 (내용을 잃지 않게)', () async {
|
|
HttpOverrides.global = null;
|
|
File(p.join(src, 'same.txt'))
|
|
..writeAsStringSync('AAAA')
|
|
..setLastModifiedSync(DateTime(2020));
|
|
File(p.join(remote.path, 'same.txt')).writeAsStringSync('BBBB'); // 같은 크기 · 더 새것 · 다른 내용
|
|
final job = TransferJob(sources: [src], dest: 'dav://nas/', move: true, contents: true);
|
|
await job.run();
|
|
expect(job.error, isNull);
|
|
expect(File(p.join(remote.path, 'same.txt')).readAsStringSync(), 'AAAA', reason: '원본 내용이 대상에 (예전에는 같다고 보고 원본만 지웠다)');
|
|
expect(File(p.join(src, 'same.txt')).existsSync(), isFalse);
|
|
expect(File(p.join(remote.path, 'a.txt')).readAsStringSync(), 'a');
|
|
});
|
|
|
|
test('214 d (WebDAV 로): 로컬 원본의 링크는 따라가지 않는다', () async {
|
|
HttpOverrides.global = null;
|
|
final outside = Directory(p.join(tmp.path, 'outside2'))..createSync();
|
|
final precious = File(p.join(outside.path, 'precious.txt'))..writeAsStringSync('keep me');
|
|
try {
|
|
Link(p.join(src, 'jn')).createSync(outside.path);
|
|
} on FileSystemException {
|
|
markTestSkipped('이 환경에서는 링크를 만들 수 없음');
|
|
return;
|
|
}
|
|
final job = TransferJob(sources: [src], dest: 'dav://nas/', move: true, contents: true);
|
|
await job.run();
|
|
expect(job.error, isNull);
|
|
expect(precious.existsSync(), isTrue);
|
|
expect(File(p.join(src, 'a.txt')).existsSync(), isFalse);
|
|
});
|
|
});
|
|
}
|