JJ_MKVMaker/test/support/sftp_server.dart

56 lines
2.1 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as p;
/// 88: SFTP 시험 서버 (tool/sftp_test_server.py, paramiko 3.5.1). 파이썬은 JJ_SFTP_PY, 없으면 ..\tools\sftp_test_py 의 venv
final sftpTestPython = Platform.environment['JJ_SFTP_PY'] ??
p.normalize(p.join(Directory.current.path, '..', 'tools', 'sftp_test_py', Platform.isWindows ? 'Scripts/python.exe' : 'bin/python'));
/// 시험 서버를 띄울 수 있는지 (없으면 그 시험은 건너뛴다)
bool get sftpTestServerAvailable => File(sftpTestPython).existsSync();
class SftpTestServer {
final Process process;
final int port;
/// 서버 호스트 키의 지문 ("SHA256:…")
final String fingerprint;
SftpTestServer._(this.process, this.port, this.fingerprint);
/// [root] 폴더를 내놓는 서버. [hostKeyFile] 이 없으면 만든다 (같은 파일이면 같은 키)
static Future<SftpTestServer> start({
required String root,
required String hostKeyFile,
String user = 'jj',
String? password = 'pw',
String? pubkey,
String keytype = 'ed25519',
bool legacyOnly = false,
}) async {
final pr = await Process.start(sftpTestPython, [
'tool/sftp_test_server.py',
'--root', root,
'--hostkey', hostKeyFile,
'--keytype', keytype,
'--user', user,
if (password != null) ...['--password', password],
if (pubkey != null) ...['--pubkey', pubkey],
if (legacyOnly) '--legacy-only',
]);
final lines = pr.stdout.transform(utf8.decoder).transform(const LineSplitter()).asBroadcastStream();
pr.stderr.drain<void>();
final port = int.parse((await lines.firstWhere((l) => l.startsWith('PORT '))).split(' ')[1]);
final fp = (await lines.firstWhere((l) => l.startsWith('FINGERPRINT '))).split(' ')[1];
return SftpTestServer._(pr, port, fp);
}
/// 끝내기 (표준 입력을 닫으면 서버가 끝난다)
Future<void> stop() async {
await process.stdin.close().catchError((_) {});
process.kill();
await process.exitCode.timeout(const Duration(seconds: 5), onTimeout: () => -1);
}
}