run the PTY tests serially instead of retrying them

The pty-tagged tests spawn real PTYs and flaked when dart test ran them in
parallel (fd contention) — papered over with retry: 2. Run that pass with
--concurrency=1 and drop the retries: serialization is the correct fix for
resource-bound tests. Verified stable across repeated runs.

T-193.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-05-31 19:01:42 +02:00
co-authored by Claude
parent 89766df55c
commit 5b739ef6a7
3 changed files with 10 additions and 7 deletions
+5 -2
View File
@@ -24,8 +24,11 @@ flutter analyze
echo "==> dart format (whole tree)"
dart format --set-exit-if-changed .
echo "==> dart test (pty — unreliable under the flutter test runner)"
dart test --tags pty test/pty/session_test.dart test/panes/registry_test.dart
echo "==> dart test (pty — unreliable under the flutter test runner; serial)"
# --concurrency=1: these spawn real PTYs and compete for fds when run in
# parallel, which flaked them (registry/session). Serialize — the proper fix
# for resource-bound tests, vs. the old per-test `retry:` band-aid. (T-193)
dart test --concurrency=1 --tags pty test/pty/session_test.dart test/panes/registry_test.dart
if [[ "$coverage" == 1 ]]; then
echo "==> flutter test --coverage (gate; unit + widget + golden + a11y)"
+1 -1
View File
@@ -43,7 +43,7 @@ void main() {
expect(evt.data['id'], pane.id);
});
test('output events base64-encode the child bytes', tags: ['pty'], retry: 2, () async {
test('output events base64-encode the child bytes', tags: ['pty'], () async {
// Subscribe to the sink stream BEFORE spawn so we don't miss
// any pane.output events that arrive between spawn and listen.
final buf = StringBuffer();
+4 -4
View File
@@ -26,7 +26,7 @@ void main() {
if (!Platform.isLinux && !Platform.isMacOS) return;
group('NativePty', () {
test('spawns shell -c echo and reads output', tags: ['pty'], retry: 2, () async {
test('spawns shell -c echo and reads output', tags: ['pty'], () async {
final s = NativePty.start(
executable: '/bin/sh',
arguments: ['-c', 'echo hello-pty'],
@@ -44,7 +44,7 @@ void main() {
expect(got, contains('hello-pty'));
});
test('write sends keystrokes to child', tags: ['pty'], retry: 2, () async {
test('write sends keystrokes to child', tags: ['pty'], () async {
final s = NativePty.start(
executable: '/bin/sh',
arguments: [],
@@ -79,7 +79,7 @@ void main() {
expect(result, contains('write-test-ok'));
});
test('close kills child and closes output', tags: ['pty'], retry: 2, () async {
test('close kills child and closes output', tags: ['pty'], () async {
final s = NativePty.start(
executable: '/bin/sh',
arguments: [],
@@ -103,7 +103,7 @@ void main() {
expect(s.isClosed, isTrue);
});
test('bare command name resolves via the PATH env var', tags: ['pty'], retry: 2, () async {
test('bare command name resolves via the PATH env var', tags: ['pty'], () async {
// 'sh' is a bare command; without resolution, execve would fail.
final s = NativePty.start(
executable: 'sh',