import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; import 'package:jj_mkvmaker/core/file_ops.dart'; import 'package:jj_mkvmaker/core/folder_size.dart'; import 'package:path/path.dart' as p; /// 80: 폴더 크기 - 필요할 때 계산 · 기억, 읽지 못한 곳은 "+", 바뀌면 그 폴더와 위 폴더를 잊음, 크기순 정렬 void main() { late Directory tmp; setUp(() { tmp = Directory.systemTemp.createTempSync('jj_fsize80_'); File(p.join(tmp.path, 'a', 'x.bin')) ..createSync(recursive: true) ..writeAsBytesSync(List.filled(1000, 0)); File(p.join(tmp.path, 'a', 'deep', 'y.bin')) ..createSync(recursive: true) ..writeAsBytesSync(List.filled(24, 0)); File(p.join(tmp.path, 'b', 'z.bin')) ..createSync(recursive: true) ..writeAsBytesSync(List.filled(5, 0)); }); tearDown(() => tmp.deleteSync(recursive: true)); Future idle(FolderSizes s, String path) async { for (var i = 0; i < 200 && s.of(path) == null; i++) { await Future.delayed(const Duration(milliseconds: 10)); } } test('안쪽 폴더까지 합 · 기억 · 바뀌면 그 폴더와 위 폴더를 잊음', () async { var reads = 0; final s = FolderSizes(list: (d) { reads++; return listEntries(d, showHidden: true); }); final a = p.join(tmp.path, 'a'); s.request(a); expect(s.busy(a), isTrue); await idle(s, a); expect(s.of(a)!.bytes, 1024); expect(s.of(a)!.partial, isFalse); final first = reads; s.request(a); await Future.delayed(const Duration(milliseconds: 20)); expect(reads, first, reason: '아는 것은 다시 읽지 않는다'); // 안쪽 폴더 크기만 잊어도 위 폴더 (a) 도 잊는다 s.request(p.join(a, 'deep')); await idle(s, p.join(a, 'deep')); s.forget(p.join(a, 'deep')); expect(s.of(a), isNull); expect(s.of(p.join(a, 'deep')), isNull); // 위 폴더를 잊으면 (새로 고침) 안쪽 폴더도 s.request(p.join(a, 'deep')); await idle(s, p.join(a, 'deep')); s.forget(tmp.path); expect(s.of(p.join(a, 'deep')), isNull); s.dispose(); }); test('읽지 못한 폴더가 있으면 "+" (실제보다 작을 수 있음)', () async { final a = p.join(tmp.path, 'a'); final s = FolderSizes(list: (d) { if (p.basename(d) == 'deep') throw const FileSystemException('권한 없음'); return listEntries(d, showHidden: true); }); s.request(a); await idle(s, a); expect(s.of(a)!.bytes, 1000); expect(s.of(a)!.label, '1000B+'); s.dispose(); }); test('크기순 정렬: 아는 폴더는 그 크기로, 모르는 폴더는 가장 작게 (폴더는 늘 위)', () { final now = DateTime(2026); final list = [ FileEntry('/r/f.bin', isDir: false, size: 10, modified: now), FileEntry('/r/small', isDir: true, modified: now), FileEntry('/r/big', isDir: true, modified: now), FileEntry('/r/unknown', isDir: true, modified: now), ]; final sizes = {'/r/small': 5, '/r/big': 5000}; final up = sortEntries(list, SortBy.size, dirSize: (d) => sizes[d.path]); expect(up.map((e) => e.name), ['unknown', 'small', 'big', 'f.bin']); final down = sortEntries(list, SortBy.size, descending: true, dirSize: (d) => sizes[d.path]); expect(down.map((e) => e.name), ['big', 'small', 'unknown', 'f.bin']); }); }