diff --git a/integration_test/ai_cancel_test.dart b/integration_test/ai_cancel_test.dart index 2eac392..5f76021 100644 --- a/integration_test/ai_cancel_test.dart +++ b/integration_test/ai_cancel_test.dart @@ -7,6 +7,7 @@ import 'package:jj_mkvmaker/core/languages.dart'; import 'package:jj_mkvmaker/core/models.dart'; import 'package:jj_mkvmaker/services/model_store.dart'; import 'package:jj_mkvmaker/services/platform_services.dart'; +import 'support/temp_dir.dart'; /// 긴 영상 (JJ_LONG_VIDEO) 의 음성인식 도중 [작업 취소] → 몇 초 안에 멈춘다 (끝까지 기다리지 않음) void main() { @@ -15,6 +16,7 @@ void main() { testWidgets('음성인식 중 취소', (tester) async { final video = Platform.environment['JJ_LONG_VIDEO']; if (video == null || !File(video).existsSync()) return markTestSkipped('JJ_LONG_VIDEO 없음'); + appTempInto(testTempDir('jj_aitmp_')); // 앱 임시 폴더 (jj_mkvmaker) 를 시험 폴더로 - 끝에 지움 (관리자 지시 10/20) final c = AppController(PlatformServices.create()); await tester.runAsync(() async { await c.init(); diff --git a/integration_test/ai_e2e_test.dart b/integration_test/ai_e2e_test.dart index 5eef314..630d163 100644 --- a/integration_test/ai_e2e_test.dart +++ b/integration_test/ai_e2e_test.dart @@ -18,6 +18,7 @@ void main() { testWidgets('영어 음성 영상 → AI 자막(ko/en/ja) → MKV', (tester) async { final dir = testTempDir('jj_e2e_'); + appTempInto(dir); // 앱 임시 폴더 (jj_mkvmaker) 도 이 아래로 - 끝에 함께 지움 (관리자 지시 10/20) final video = p.join(dir.path, '영어 강의.mp4'); final speech = p.join(Directory.current.path, 'test_assets', 'speech_en.wav'); final r = await Process.run('ffmpeg', [ diff --git a/integration_test/ai_long_test.dart b/integration_test/ai_long_test.dart index 2c16f45..f4d924a 100644 --- a/integration_test/ai_long_test.dart +++ b/integration_test/ai_long_test.dart @@ -8,6 +8,7 @@ import 'package:jj_mkvmaker/core/models.dart'; import 'package:jj_mkvmaker/core/output_paths.dart'; import 'package:jj_mkvmaker/services/model_store.dart'; import 'package:jj_mkvmaker/services/platform_services.dart'; +import 'support/temp_dir.dart'; /// 긴 실제 영상 (JJ_LONG_VIDEO) 으로 AI 자막: 원어 자동 → [JJ_LONG_TARGETS] (기본 ja,en). /// 번역이 제대로 됐는지 줄 단위로 센다 (영어 자막에 일본어가 남은 줄 · 빈 줄 · 같은 말 되풀이). @@ -18,6 +19,7 @@ void main() { final video = Platform.environment['JJ_LONG_VIDEO']; if (video == null || !File(video).existsSync()) return markTestSkipped('JJ_LONG_VIDEO 없음'); final targets = (Platform.environment['JJ_LONG_TARGETS'] ?? 'ja,en').split(','); + appTempInto(testTempDir('jj_aitmp_')); // 앱 임시 폴더 (jj_mkvmaker) 를 시험 폴더로 - 끝에 지움 (관리자 지시 10/20) final c = AppController(PlatformServices.create()); final sw = Stopwatch()..start(); await tester.runAsync(() async { diff --git a/integration_test/cef_dns_real_test.dart b/integration_test/cef_dns_real_test.dart index e5f74d2..b46952c 100644 --- a/integration_test/cef_dns_real_test.dart +++ b/integration_test/cef_dns_real_test.dart @@ -34,7 +34,7 @@ void main() { } CefRuntime.rememberStartState(); expect(CefRuntime.readyThisRun, isTrue); - final data = Platform.environment['JJ_MKVMAKER_DATA'] ?? testTempDir('jj_cef_real_').path; + final data = Platform.environment['JJ_MKVMAKER_DATA'] ?? testTempDir('jj_cef_real_', heldByApp: true).path; Directory(data).createSync(recursive: true); final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); c.settings diff --git a/integration_test/dns_block_real_test.dart b/integration_test/dns_block_real_test.dart index f38fd6b..61bfe2e 100644 --- a/integration_test/dns_block_real_test.dart +++ b/integration_test/dns_block_real_test.dart @@ -21,7 +21,7 @@ void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); testWidgets('250: 닿지 않는 DNS → 브라우저에 앱 덮개 (Edge 실제)', (tester) async { - final data = Platform.environment['JJ_MKVMAKER_DATA'] ?? testTempDir('jj_dns_block_').path; + final data = Platform.environment['JJ_MKVMAKER_DATA'] ?? testTempDir('jj_dns_block_', heldByApp: true).path; Directory(data).createSync(recursive: true); final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); c.settings diff --git a/integration_test/support/temp_dir.dart b/integration_test/support/temp_dir.dart index 6756c2c..1c5a509 100644 --- a/integration_test/support/temp_dir.dart +++ b/integration_test/support/temp_dir.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; +import 'package:jj_mkvmaker/platform/windows/desktop_storage_service.dart'; /// 관리자 지시 (10/19, 28 이 찾음): 통합 시험 · 캡처가 %TEMP%\jj_* 시험 폴더를 남겼다 - 시험 끝 (실패해도) 에 지운다. /// [base] 가 있으면 그 아래 (짧은 경로가 필요한 캡처). 반드시 시험 (testWidgets · test) 안에서 부른다 (addTearDown). @@ -14,6 +15,15 @@ Directory testTempDir(String prefix, {String? base, bool heldByApp = false}) { return dir; } +/// 관리자 지시 (10/20): 앱 임시 폴더 ([DesktopStorageService.tempDirectory] = %TEMP%\jj_mkvmaker) 를 이 시험 폴더 아래로 돌린다 +/// (ai_e2e 가 남겨 test_temp_check 가 exit 2). 시험 끝에 기준을 되돌리고, 폴더는 [testTempDir] 의 정리가 함께 지운다 +/// (addTearDown 은 나중에 넣은 것부터 돌아 앱 기준을 먼저 되돌린다). 사용자 %TEMP%\jj_mkvmaker 는 건드리지 않는다 +void appTempInto(Directory dir) { + final before = DesktopStorageService.tempRoot; + DesktopStorageService.tempRoot = dir.path; + addTearDown(() => DesktopStorageService.tempRoot = before); +} + /// 관리자 지시 (10/20): tool/test_temp_check.ps1 이 TEMP · TMP 를 실행 폴더 (%TEMP%\t_jjrun_<표>) 로 돌리고 표를 JJ_TEST_TMP_TAG 로 넘긴다. /// 표가 있는데 임시 폴더가 그 밖에 생기면 (환경 변수가 시험 · 앱까지 오지 않음) 다른 세션 시험과 섞이므로 시험을 실패시킨다 void expectInTaggedTemp(Directory dir) { diff --git a/integration_test/tor_dns_real_test.dart b/integration_test/tor_dns_real_test.dart index 7570d25..ab3ee8b 100644 --- a/integration_test/tor_dns_real_test.dart +++ b/integration_test/tor_dns_real_test.dart @@ -27,7 +27,7 @@ void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); testWidgets('DNS 강제 · Tor 화면 실제 연결', (tester) async { - final data = Platform.environment['JJ_MKVMAKER_DATA'] ?? testTempDir('jj_tor_real_').path; + final data = Platform.environment['JJ_MKVMAKER_DATA'] ?? testTempDir('jj_tor_real_', heldByApp: true).path; Directory(data).createSync(recursive: true); ComponentStore.dataDirectory = data; ComponentStore.shared = ComponentStore(data); diff --git a/tool/test_temp_check.ps1 b/tool/test_temp_check.ps1 index cbb7224..3efaba5 100644 --- a/tool/test_temp_check.ps1 +++ b/tool/test_temp_check.ps1 @@ -55,9 +55,15 @@ if ($left.Count -gt 0) { Write-Host ("시험이 남긴 임시 폴더 {0}개 ({1}):" -f $left.Count, $run) $left | Sort-Object | ForEach-Object { Write-Host " $_" } } -# 실행 폴더는 이 스크립트가 만든 것이라 통째로 지운다 (긴 경로는 \\?\ 로) -cmd /c "rd /s /q `"\\?\$run`"" 2>$null -if (Test-Path -LiteralPath $run) { Write-Host "실행 폴더를 다 지우지 못함: $run" } +# 실행 폴더는 이 스크립트가 만든 것이라 통째로 지운다 (긴 경로는 \\?\ 로). +# 관리자 지시 (10/20): Edge (WebView2) 는 시험 앱이 끝난 뒤에도 몇 초 사용자 데이터 (jj_held_) 를 잡고 있다 - 놓을 때까지 몇 번 다시 해 본다. +# rd 의 오류는 cmd 안에서 버린다 (PowerShell 쪽 2>$null 은 $ErrorActionPreference = 'Stop' 에서 오류가 되어 시험이 다 통과해도 exit 1 이었다). +# 지우는 것은 이 실행 폴더 안뿐이다 (사용자 폴더 · 다른 세션의 %TEMP% 는 건드리지 않음) +for ($i = 0; $i -lt 30 -and (Test-Path -LiteralPath $run); $i++) { + if ($i -gt 0) { Start-Sleep -Seconds 2 } + cmd /c "rd /s /q `"\\?\$run`" 2>nul" +} +if (Test-Path -LiteralPath $run) { Write-Host "실행 폴더를 다 지우지 못함 (1분 기다림): $run" } if ($left.Count -gt 0) { if ($code -eq 0) { exit 2 } } else {