JJ_MKVMaker/test/ytdlp_plain_file_test.dart

67 lines
3.6 KiB
Dart

import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:jj_mkvmaker/core/download_detect.dart';
import 'package:jj_mkvmaker/platform/windows/ytdlp_backend.dart';
import 'package:jj_mkvmaker/services/downloader.dart';
import 'package:path/path.dart' as p;
/// 184-2: 확장자가 없는 주소의 동영상이 아닌 파일 - yt-dlp 가 다 받은 뒤 후처리에서 실패해도 받은 파일을 원래 이름으로 남기고 완료
void main() {
test('원래 이름: 물음표 뒤 파일 이름 → 경로 끝 → 받은 이름에서 [id] · .unknown_video 빼기', () {
expect(nonVideoFileName('https://a.com/download.php?id=3&file=docs/report.zip', 'x [1].unknown_video'), 'report.zip');
expect(nonVideoFileName('https://a.com/files/setup.exe?token=abc', 'x'), 'setup.exe');
expect(nonVideoFileName('https://a.com/get.php?id=3', r'C:\d\get [get].unknown_video'), 'get');
expect(nonVideoFileName('https://a.com/dl/12345', r'C:\d\12345 [12345].bin'), '12345.bin');
});
test('후처리 "동영상이 아님" 오류만 고른다', () {
expect(isNonVideoPostprocessError('ERROR: Postprocessing: Error opening input files: Invalid data found when processing input'), isTrue);
expect(isNonVideoPostprocessError('ERROR: [generic] Unable to download webpage: HTTP Error 404'), isFalse);
});
test('yt-dlp 가 받은 뒤 후처리에서 실패 → 원래 이름으로 남기고 완료, 같은 이름은 덮지 않음', () async {
final dir = Directory.systemTemp.createTempSync('jj_plain_');
addTearDown(() => dir.deleteSync(recursive: true));
File(p.join(dir.path, 'report.zip')).writeAsStringSync('old');
// 가짜 yt-dlp: 파일을 만들고 "Destination" 을 알린 뒤 후처리 오류로 끝
final script = File(p.join(dir.path, 'fake_ytdlp.py'))
..writeAsStringSync(r'''
import os, sys
a = sys.argv[1:]
d = a[a.index('-P') + 1]
f = os.path.join(d, 'download [download].unknown_video')
open(f, 'w').write('PK')
print('[download] Destination: ' + f, flush=True)
sys.stderr.write('ERROR: Postprocessing: Error opening input files: Invalid data found when processing input\n')
sys.exit(1)
''');
final out = Directory(p.join(dir.path, 'out'))..createSync();
File(p.join(out.path, 'report.zip')).writeAsStringSync('old');
final backend = YtDlpBackend(ytdlp: 'python', prefixArgs: [script.path], deno: '');
final t = DownloadTask(
id: '1', kind: DownloadKind.video, source: 'https://a.com/download.php?file=report.zip', dir: out.path);
await backend.start(t, () {});
expect(t.state, DownloadState.done, reason: t.error);
expect(t.files, [p.join(out.path, 'report (2).zip')]);
expect(File(t.files.single).readAsStringSync(), 'PK');
expect(File(p.join(out.path, 'report.zip')).readAsStringSync(), 'old', reason: '있던 파일은 덮지 않음');
expect(File(p.join(out.path, 'download [download].unknown_video')).existsSync(), isFalse);
});
test('받은 파일이 없으면 그대로 실패', () async {
final dir = Directory.systemTemp.createTempSync('jj_plain_');
addTearDown(() => dir.deleteSync(recursive: true));
final script = File(p.join(dir.path, 'fake_ytdlp.py'))
..writeAsStringSync(r'''
import sys
sys.stderr.write('ERROR: Postprocessing: Invalid data found when processing input\n')
sys.exit(1)
''');
final backend = YtDlpBackend(ytdlp: 'python', prefixArgs: [script.path], deno: '');
final t = DownloadTask(id: '1', kind: DownloadKind.video, source: 'https://a.com/x', dir: dir.path);
await backend.start(t, () {});
expect(t.state, DownloadState.failed);
});
}