JJ_MKVMaker/test/delete_ops_contract_test.dart

76 lines
3.4 KiB
Dart

import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:jj_mkvmaker/app/delete_ops.dart';
import 'package:jj_mkvmaker/core/app_trash.dart';
import 'package:path/path.dart' as p;
import 'support/fake_recycle_bin.dart' show realRecycleSkip;
/// E5b 약속 시험: lib/app/delete_ops.dart 맨 위 약속. 시험 폴더의 실제 파일 · 실제 앱 휴지통 (가짜 없음).
/// Windows 휴지통은 실제 사용자 휴지통이라 JJ_TEST_REAL_RECYCLE=1 일 때만 (끝나면 되살려 흔적 없음).
void main() {
if (!Platform.isWindows) return; // 열려 있는 파일을 못 지우는 것은 Windows
late Directory tmp;
late String a, b, dir, locked;
late RandomAccessFile hold;
setUp(() {
tmp = Directory.systemTemp.createTempSync('jj_del_');
a = p.join(tmp.path, 'a.txt');
b = p.join(tmp.path, 'b.txt');
dir = p.join(tmp.path, 'Show');
locked = p.join(tmp.path, 'locked.txt');
File(a).writeAsStringSync('a');
File(b).writeAsStringSync('b');
Directory(dir).createSync();
File(p.join(dir, 'ep.mkv')).writeAsStringSync('x');
File(locked).writeAsStringSync('l');
hold = File(locked).openSync(mode: FileMode.append); // Windows: 열려 있는 파일은 지울 수 없다
});
tearDown(() {
hold.closeSync();
tmp.deleteSync(recursive: true);
});
test('영구: 하나가 실패해도 나머지는 지우고 실패를 이유와 함께 (열려 있는 파일)', () async {
final r = await deletePaths([a, locked, dir], permanent: true);
expect(File(a).existsSync(), isFalse);
expect(Directory(dir).existsSync(), isFalse);
expect([for (final (x, _) in r.failed) x], [locked]);
expect(File(locked).existsSync(), isTrue);
expect(r.failed.single.$2, isNotEmpty);
expect([r.sent, r.trashed, r.tooLong], everyElement(isEmpty));
});
test('앱 휴지통: 보내고 되살림 · 못 보낸 것은 몰래 지우지 않고 보고 · deleteForever', () async {
final trash = AppTrash([tmp.path]);
final outside = Directory.systemTemp.createTempSync('jj_del_out_');
addTearDown(() => outside.deleteSync(recursive: true));
final far = p.join(outside.path, 'far.txt');
File(far).writeAsStringSync('f');
final r = await deletePaths([a, dir, far], permanent: false, trash: trash);
expect([File(a).existsSync(), Directory(dir).existsSync()], [false, false]);
expect(r.undoable, [a, dir]);
expect(r.recycled, 2);
expect([for (final (x, _) in r.notTrashed) x], [far], reason: '저장 장치 밖');
expect(File(far).existsSync(), isTrue, reason: '몰래 영구 삭제하지 않음');
final back = await undoTrash(trash, r.trashed);
expect(back.length, 2);
expect([File(a).existsSync(), File(p.join(dir, 'ep.mkv')).existsSync()], [true, true]);
expect([for (final (x, _) in await deleteForever([far, locked])) x], [locked]);
expect(File(far).existsSync(), isFalse);
expect(deleteFailReason(const FileSystemException('x', 'y', OSError('잠김', 32))), '잠김');
});
test('Windows 휴지통: 보내고 되돌림 (실제 휴지통)', () async {
final r = await deletePaths([a, b], permanent: false);
expect(r.sent, [a, b]);
expect(r.recycled, 2);
expect(File(a).existsSync(), isFalse);
final u = undoRecycle(r.sent, r.since);
expect(u.back, 2);
expect(u.failed, isEmpty);
expect([File(a).existsSync(), File(b).existsSync()], [true, true]);
}, skip: realRecycleSkip);
}