From c8dd80604d0e910b5b6e45ab4aa7bc3b78df57b9 Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Fri, 21 Nov 2025 05:43:49 +0100 Subject: [PATCH 1/2] Better port allocation to reduce port conflicts in integration tests on CI. --- .../lib/src/fake_pub_server_process.dart | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/pkg/pub_integration/lib/src/fake_pub_server_process.dart b/pkg/pub_integration/lib/src/fake_pub_server_process.dart index 3f77c46565..b68e1c1a88 100644 --- a/pkg/pub_integration/lib/src/fake_pub_server_process.dart +++ b/pkg/pub_integration/lib/src/fake_pub_server_process.dart @@ -5,13 +5,10 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'dart:math'; import 'package:path/path.dart' as p; import 'package:retry/retry.dart'; -final _random = Random.secure(); - /// The timeout factor that should be used in integration tests. final testTimeoutFactor = 6; @@ -33,14 +30,13 @@ class FakePubServerProcess { this._coverageConfig, ); - static Future start({String? appDir, int? port}) async { + static Future start({String? appDir}) async { appDir ??= p.join(Directory.current.path, '../../app'); - // TODO: check for free port - port ??= 20000 + _random.nextInt(990); - final storagePort = port + 1; - final searchPort = port + 2; - final analyzerPort = port + 3; - final vmPort = port + 5; + final port = await _getFreePort(); + final storagePort = await _getFreePort(); + final searchPort = await _getFreePort(); + final analyzerPort = await _getFreePort(); + final vmPort = await _getFreePort(); final coverageConfig = await _CoverageConfig.detect(vmPort); await _runPubGet(appDir); @@ -316,3 +312,10 @@ void _writeLogs(Stream> stream, String prefix) { }, ); } + +Future _getFreePort() async { + final server = await HttpServer.bind('localhost', 0); + final port = server.port; + await server.close(); + return port; +} From d32817a6975bd274060131e31af97e16db9fff8a Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Fri, 21 Nov 2025 05:57:41 +0100 Subject: [PATCH 2/2] also track storagePort --- pkg/pub_integration/lib/src/fake_pub_server_process.dart | 3 +++ pkg/pub_integration/lib/src/fake_test_context_provider.dart | 2 ++ pkg/pub_integration/test/exported_bucket_test.dart | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/pub_integration/lib/src/fake_pub_server_process.dart b/pkg/pub_integration/lib/src/fake_pub_server_process.dart index b68e1c1a88..69e7540987 100644 --- a/pkg/pub_integration/lib/src/fake_pub_server_process.dart +++ b/pkg/pub_integration/lib/src/fake_pub_server_process.dart @@ -15,6 +15,7 @@ final testTimeoutFactor = 6; /// Wrapper and helper methods around the fake server process. class FakePubServerProcess { final int port; + final int storagePort; final String _tmpDir; final Process _process; final _CoverageConfig? _coverageConfig; @@ -25,6 +26,7 @@ class FakePubServerProcess { FakePubServerProcess._( this.port, + this.storagePort, this._tmpDir, this._process, this._coverageConfig, @@ -66,6 +68,7 @@ class FakePubServerProcess { ); final instance = FakePubServerProcess._( port, + storagePort, tmpDir.path, process, coverageConfig, diff --git a/pkg/pub_integration/lib/src/fake_test_context_provider.dart b/pkg/pub_integration/lib/src/fake_test_context_provider.dart index b3a8f49c63..167c3eb016 100644 --- a/pkg/pub_integration/lib/src/fake_test_context_provider.dart +++ b/pkg/pub_integration/lib/src/fake_test_context_provider.dart @@ -53,6 +53,8 @@ class TestContextProvider { return TestContextProvider._(origin, fakePubServerProcess, testBrowser); } + int get storagePort => _fakePubServerProcess.storagePort; + Future close() async { await _testBrowser.close(); await _fakePubServerProcess.kill(); diff --git a/pkg/pub_integration/test/exported_bucket_test.dart b/pkg/pub_integration/test/exported_bucket_test.dart index 83ac15b9dd..b57ffa5d9f 100644 --- a/pkg/pub_integration/test/exported_bucket_test.dart +++ b/pkg/pub_integration/test/exported_bucket_test.dart @@ -28,7 +28,7 @@ void main() { final pubUri = Uri.parse(fakeTestScenario.pubHostedUrl); final storageUri = pubUri.replace( - port: pubUri.port + 1, + port: fakeTestScenario.storagePort, path: '/fake-exported-apis/latest', );