blob: 054d430c10899002b7dd865f152938101da0cada [file] [log] [blame]
// Copyright 2024 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path;
typedef TestDtdConnectionInfo = ({
String? uri,
String? secret,
Process? dtdProcess,
});
/// Helper method to start DTD for the purpose of testing.
Future<TestDtdConnectionInfo> startDtd() async {
const dtdConnectTimeout = Duration(seconds: 10);
final completer = Completer<TestDtdConnectionInfo>();
Process? dtdProcess;
StreamSubscription? dtdStoutSubscription;
TestDtdConnectionInfo onFailure() =>
(uri: null, secret: null, dtdProcess: dtdProcess);
try {
dtdProcess = await Process.start(
Platform.resolvedExecutable,
['tooling-daemon', '--machine'],
);
dtdStoutSubscription = dtdProcess.stdout.listen((List<int> data) {
try {
final decoded = utf8.decode(data);
final json = jsonDecode(decoded) as Map<String, Object?>;
if (json
case {
'tooling_daemon_details': {
'uri': final String uri,
'trusted_client_secret': final String secret,
}
}) {
completer.complete(
(uri: uri, secret: secret, dtdProcess: dtdProcess),
);
} else {
completer.complete(onFailure());
}
} catch (e) {
completer.complete(onFailure());
}
});
return completer.future
.timeout(dtdConnectTimeout, onTimeout: onFailure)
.then((value) async {
await dtdStoutSubscription?.cancel();
return value;
});
} catch (e) {
await dtdStoutSubscription?.cancel();
return onFailure();
}
}
class TestDartApp {
static final dartVMServiceRegExp = RegExp(
r'The Dart VM service is listening on (http://127.0.0.1:.*)',
);
final directory = Directory('tmp/test_app');
Process? process;
Future<String> start() async {
_initTestApp();
process = await Process.start(
Platform.resolvedExecutable,
['--observe=0', 'run', 'bin/main.dart'],
workingDirectory: directory.path,
);
final serviceUriCompleter = Completer<String>();
late StreamSubscription sub;
sub = process!.stdout
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen((line) async {
if (line.contains(dartVMServiceRegExp)) {
await sub.cancel();
serviceUriCompleter.complete(
dartVMServiceRegExp.firstMatch(line)!.group(1),
);
}
});
return await serviceUriCompleter.future.timeout(
const Duration(seconds: 5),
onTimeout: () async {
await sub.cancel();
return '';
},
);
}
Future<void> kill() async {
process?.kill();
await process?.exitCode;
process = null;
if (directory.existsSync()) directory.deleteSync(recursive: true);
}
void _initTestApp() {
if (directory.existsSync()) {
directory.deleteSync(recursive: true);
}
directory.createSync(recursive: true);
final mainFile = File(path.join(directory.path, 'bin', 'main.dart'))
..createSync(recursive: true);
mainFile.writeAsStringSync('''
import 'dart:async';
void main() async {
for (int i = 0; i < 10000; i++) {
await Future.delayed(const Duration(seconds: 2));
}
}
''');
}
}