Unverified Commit 0420d563 authored by Yegor's avatar Yegor Committed by GitHub

consolidate all web integration tests under the same shard (#82307)

* consolidate all web integration tests under the same shard
parent 13a72114
...@@ -140,16 +140,6 @@ task: ...@@ -140,16 +140,6 @@ task:
- (cd dev/bots; pub get) - (cd dev/bots; pub get)
- dart --enable-asserts ./dev/bots/test.dart - dart --enable-asserts ./dev/bots/test.dart
- name: web_integration_tests
only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/**', 'packages/flutter_web_plugins/**', 'bin/**') && $CIRRUS_PR != ''"
environment:
# As of October 2019, the Web shards needed more than 6G of RAM.
CPU: 2
MEMORY: 8G
CHROME_NO_SANDBOX: true
script:
- dart --enable-asserts ./dev/bots/test.dart
- name: docs-linux # linux-only - name: docs-linux # linux-only
environment: environment:
CPU: 4 CPU: 4
......
...@@ -12,6 +12,7 @@ import 'package:shelf/shelf.dart'; ...@@ -12,6 +12,7 @@ import 'package:shelf/shelf.dart';
import 'browser.dart'; import 'browser.dart';
import 'run_command.dart'; import 'run_command.dart';
import 'test/common.dart'; import 'test/common.dart';
import 'utils.dart';
final String _bat = Platform.isWindows ? '.bat' : ''; final String _bat = Platform.isWindows ? '.bat' : '';
final String _flutterRoot = path.dirname(path.dirname(path.dirname(path.fromUri(Platform.script)))); final String _flutterRoot = path.dirname(path.dirname(path.dirname(path.fromUri(Platform.script))));
...@@ -53,215 +54,231 @@ Future<void> _rebuildApp({ @required int version }) async { ...@@ -53,215 +54,231 @@ Future<void> _rebuildApp({ @required int version }) async {
); );
} }
/// A drop-in replacement for `package:test` expect that can run outside the
/// test zone.
void expect(Object actual, Object expected) {
final Matcher matcher = wrapMatcher(expected);
final Map<Object, Object> matchState = <Object, Object>{};
if (matcher.matches(actual, matchState)) {
return;
}
final StringDescription mismatchDescription = StringDescription();
matcher.describeMismatch(actual, mismatchDescription, matchState, true);
throw TestFailure(mismatchDescription.toString());
}
Future<void> runWebServiceWorkerTest({ Future<void> runWebServiceWorkerTest({
@required bool headless, @required bool headless,
}) async { }) async {
test('flutter_service_worker.js', () async { await _rebuildApp(version: 1);
await _rebuildApp(version: 1);
final Map<String, int> requestedPathCounts = <String, int>{}; final Map<String, int> requestedPathCounts = <String, int>{};
void expectRequestCounts(Map<String, int> expectedCounts) { void expectRequestCounts(Map<String, int> expectedCounts) {
expect(requestedPathCounts, expectedCounts); expect(requestedPathCounts, expectedCounts);
requestedPathCounts.clear(); requestedPathCounts.clear();
} }
AppServer server; AppServer server;
Future<void> waitForAppToLoad(Map<String, int> waitForCounts) async { Future<void> waitForAppToLoad(Map<String, int> waitForCounts) async {
print('Waiting for app to load $waitForCounts'); print('Waiting for app to load $waitForCounts');
await Future.any(<Future<void>>[ await Future.any(<Future<void>>[
() async { () async {
while (!waitForCounts.entries.every((MapEntry<String, int> entry) => (requestedPathCounts[entry.key] ?? 0) >= entry.value)) { while (!waitForCounts.entries.every((MapEntry<String, int> entry) => (requestedPathCounts[entry.key] ?? 0) >= entry.value)) {
await Future<void>.delayed(const Duration(milliseconds: 100)); await Future<void>.delayed(const Duration(milliseconds: 100));
} }
}(), }(),
server.onChromeError.then((String error) { server.onChromeError.then((String error) {
throw Exception('Chrome error: $error'); throw Exception('Chrome error: $error');
}), }),
]); ]);
} }
String reportedVersion; String reportedVersion;
Future<void> startAppServer({ Future<void> startAppServer({
@required String cacheControl, @required String cacheControl,
}) async { }) async {
server = await AppServer.start( final int serverPort = await findAvailablePort();
headless: headless, final int browserDebugPort = await findAvailablePort();
cacheControl: cacheControl, server = await AppServer.start(
appUrl: 'http://localhost:8080/index.html', headless: headless,
appDirectory: _appBuildDirectory, cacheControl: cacheControl,
additionalRequestHandlers: <Handler>[ // TODO(yjbanov): use a better port disambiguation strategy than trying
(Request request) { // to guess what ports other tests use.
final String requestedPath = request.url.path; appUrl: 'http://localhost:$serverPort/index.html',
requestedPathCounts.putIfAbsent(requestedPath, () => 0); serverPort: serverPort,
requestedPathCounts[requestedPath] += 1; browserDebugPort: browserDebugPort,
if (requestedPath == 'CLOSE') { appDirectory: _appBuildDirectory,
reportedVersion = request.url.queryParameters['version']; additionalRequestHandlers: <Handler>[
return Response.ok('OK'); (Request request) {
} final String requestedPath = request.url.path;
return Response.notFound(''); requestedPathCounts.putIfAbsent(requestedPath, () => 0);
}, requestedPathCounts[requestedPath] += 1;
], if (requestedPath == 'CLOSE') {
); reportedVersion = request.url.queryParameters['version'];
} return Response.ok('OK');
}
return Response.notFound('');
},
],
);
}
try { try {
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
// Caching server // Caching server
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
print('With cache: test first page load'); print('With cache: test first page load');
await startAppServer(cacheControl: 'max-age=3600'); await startAppServer(cacheControl: 'max-age=3600');
await waitForAppToLoad(<String, int>{ await waitForAppToLoad(<String, int>{
'CLOSE': 1, 'CLOSE': 1,
'flutter_service_worker.js': 1, 'flutter_service_worker.js': 1,
}); });
expectRequestCounts(<String, int>{ expectRequestCounts(<String, int>{
'': 1, '': 1,
// Even though the server is caching index.html is downloaded twice, // Even though the server is caching index.html is downloaded twice,
// once by the initial page load, and once by the service worker. // once by the initial page load, and once by the service worker.
// Other resources are loaded once only by the service worker. // Other resources are loaded once only by the service worker.
'index.html': 2, 'index.html': 2,
'main.dart.js': 1, 'main.dart.js': 1,
'flutter_service_worker.js': 1, 'flutter_service_worker.js': 1,
'assets/FontManifest.json': 1, 'assets/FontManifest.json': 1,
'assets/NOTICES': 1, 'assets/NOTICES': 1,
'assets/AssetManifest.json': 1, 'assets/AssetManifest.json': 1,
'CLOSE': 1, 'CLOSE': 1,
// In headless mode Chrome does not load 'manifest.json' and 'favicon.ico'. // In headless mode Chrome does not load 'manifest.json' and 'favicon.ico'.
if (!headless) if (!headless)
...<String, int>{ ...<String, int>{
'manifest.json': 1, 'manifest.json': 1,
'favicon.ico': 1, 'favicon.ico': 1,
} }
}); });
expect(reportedVersion, '1'); expect(reportedVersion, '1');
reportedVersion = null; reportedVersion = null;
print('With cache: test page reload'); print('With cache: test page reload');
await server.chrome.reloadPage(); await server.chrome.reloadPage();
await waitForAppToLoad(<String, int>{ await waitForAppToLoad(<String, int>{
'CLOSE': 1, 'CLOSE': 1,
'flutter_service_worker.js': 1, 'flutter_service_worker.js': 1,
}); });
expectRequestCounts(<String, int>{ expectRequestCounts(<String, int>{
'flutter_service_worker.js': 1, 'flutter_service_worker.js': 1,
'CLOSE': 1, 'CLOSE': 1,
}); });
expect(reportedVersion, '1'); expect(reportedVersion, '1');
reportedVersion = null; reportedVersion = null;
print('With cache: test page reload after rebuild'); print('With cache: test page reload after rebuild');
await _rebuildApp(version: 2); await _rebuildApp(version: 2);
// Since we're caching, we need to ignore cache when reloading the page. // Since we're caching, we need to ignore cache when reloading the page.
await server.chrome.reloadPage(ignoreCache: true); await server.chrome.reloadPage(ignoreCache: true);
await waitForAppToLoad(<String, int>{ await waitForAppToLoad(<String, int>{
'CLOSE': 1, 'CLOSE': 1,
'flutter_service_worker.js': 2, 'flutter_service_worker.js': 2,
}); });
expectRequestCounts(<String, int>{ expectRequestCounts(<String, int>{
'index.html': 2, 'index.html': 2,
'flutter_service_worker.js': 2, 'flutter_service_worker.js': 2,
'': 1, '': 1,
'main.dart.js': 1, 'main.dart.js': 1,
'assets/NOTICES': 1, 'assets/NOTICES': 1,
'assets/AssetManifest.json': 1, 'assets/AssetManifest.json': 1,
'assets/FontManifest.json': 1, 'assets/FontManifest.json': 1,
'CLOSE': 1, 'CLOSE': 1,
if (!headless) if (!headless)
'favicon.ico': 1, 'favicon.ico': 1,
}); });
expect(reportedVersion, '2'); expect(reportedVersion, '2');
reportedVersion = null; reportedVersion = null;
await server.stop(); await server.stop();
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
// Non-caching server // Non-caching server
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
print('No cache: test first page load'); print('No cache: test first page load');
await _rebuildApp(version: 3); await _rebuildApp(version: 3);
await startAppServer(cacheControl: 'max-age=0'); await startAppServer(cacheControl: 'max-age=0');
await waitForAppToLoad(<String, int>{ await waitForAppToLoad(<String, int>{
'CLOSE': 1, 'CLOSE': 1,
'flutter_service_worker.js': 1, 'flutter_service_worker.js': 1,
}); });
expectRequestCounts(<String, int>{ expectRequestCounts(<String, int>{
'': 1, '': 1,
'index.html': 2, 'index.html': 2,
// We still download some resources multiple times if the server is non-caching. // We still download some resources multiple times if the server is non-caching.
'main.dart.js': 2, 'main.dart.js': 2,
'assets/FontManifest.json': 2, 'assets/FontManifest.json': 2,
'flutter_service_worker.js': 1, 'flutter_service_worker.js': 1,
'assets/NOTICES': 1, 'assets/NOTICES': 1,
'assets/AssetManifest.json': 1, 'assets/AssetManifest.json': 1,
'CLOSE': 1, 'CLOSE': 1,
// In headless mode Chrome does not load 'manifest.json' and 'favicon.ico'. // In headless mode Chrome does not load 'manifest.json' and 'favicon.ico'.
if (!headless) if (!headless)
...<String, int>{ ...<String, int>{
'manifest.json': 1, 'manifest.json': 1,
'favicon.ico': 1, 'favicon.ico': 1,
} }
}); });
expect(reportedVersion, '3'); expect(reportedVersion, '3');
reportedVersion = null; reportedVersion = null;
print('No cache: test page reload'); print('No cache: test page reload');
await server.chrome.reloadPage(); await server.chrome.reloadPage();
await waitForAppToLoad(<String, int>{ await waitForAppToLoad(<String, int>{
'CLOSE': 1, 'CLOSE': 1,
'flutter_service_worker.js': 1, 'flutter_service_worker.js': 1,
}); });
expectRequestCounts(<String, int>{ expectRequestCounts(<String, int>{
'flutter_service_worker.js': 1, 'flutter_service_worker.js': 1,
'CLOSE': 1, 'CLOSE': 1,
if (!headless) if (!headless)
'manifest.json': 1, 'manifest.json': 1,
}); });
expect(reportedVersion, '3'); expect(reportedVersion, '3');
reportedVersion = null; reportedVersion = null;
print('No cache: test page reload after rebuild'); print('No cache: test page reload after rebuild');
await _rebuildApp(version: 4); await _rebuildApp(version: 4);
// TODO(yjbanov): when running Chrome with DevTools protocol, for some // TODO(yjbanov): when running Chrome with DevTools protocol, for some
// reason a hard refresh is still required. This works without a hard // reason a hard refresh is still required. This works without a hard
// refresh when running Chrome manually as normal. At the time of writing // refresh when running Chrome manually as normal. At the time of writing
// this test I wasn't able to figure out what's wrong with the way we run // this test I wasn't able to figure out what's wrong with the way we run
// Chrome from tests. // Chrome from tests.
await server.chrome.reloadPage(ignoreCache: true); await server.chrome.reloadPage(ignoreCache: true);
await waitForAppToLoad(<String, int>{ await waitForAppToLoad(<String, int>{
'CLOSE': 1, 'CLOSE': 1,
'flutter_service_worker.js': 1, 'flutter_service_worker.js': 1,
}); });
expectRequestCounts(<String, int>{ expectRequestCounts(<String, int>{
'': 1, '': 1,
'index.html': 2, 'index.html': 2,
'flutter_service_worker.js': 2, 'flutter_service_worker.js': 2,
'main.dart.js': 2, 'main.dart.js': 2,
'assets/NOTICES': 1, 'assets/NOTICES': 1,
'assets/AssetManifest.json': 1, 'assets/AssetManifest.json': 1,
'assets/FontManifest.json': 2, 'assets/FontManifest.json': 2,
'CLOSE': 1, 'CLOSE': 1,
if (!headless) if (!headless)
...<String, int>{ ...<String, int>{
'manifest.json': 1, 'manifest.json': 1,
'favicon.ico': 1, 'favicon.ico': 1,
} }
}); });
expect(reportedVersion, '4'); expect(reportedVersion, '4');
reportedVersion = null; reportedVersion = null;
} finally { } finally {
await _setAppVersion(1); await _setAppVersion(1);
await server?.stop(); await server?.stop();
} }
// This is a long test. The default 30 seconds is not enough.
}, timeout: const Timeout(Duration(minutes: 10)));
} }
...@@ -108,8 +108,9 @@ Future<void> main(List<String> args) async { ...@@ -108,8 +108,9 @@ Future<void> main(List<String> args) async {
'tool_tests': _runToolTests, 'tool_tests': _runToolTests,
'web_tool_tests': _runToolTests, 'web_tool_tests': _runToolTests,
'tool_integration_tests': _runIntegrationToolTests, 'tool_integration_tests': _runIntegrationToolTests,
// All the unit/widget tests run using `flutter test --platform=chrome`
'web_tests': _runWebUnitTests, 'web_tests': _runWebUnitTests,
'web_integration_tests': _runWebIntegrationTests, // All web integration tests
'web_long_running_tests': _runWebLongRunningTests, 'web_long_running_tests': _runWebLongRunningTests,
'flutter_plugins': _runFlutterPluginsTests, 'flutter_plugins': _runFlutterPluginsTests,
'skp_generator': _runSkpGeneratorTests, 'skp_generator': _runSkpGeneratorTests,
...@@ -850,6 +851,34 @@ Future<void> _runWebLongRunningTests() async { ...@@ -850,6 +851,34 @@ Future<void> _runWebLongRunningTests() async {
() => _runGalleryE2eWebTest('release'), () => _runGalleryE2eWebTest('release'),
() => _runGalleryE2eWebTest('release', canvasKit: true), () => _runGalleryE2eWebTest('release', canvasKit: true),
() => runWebServiceWorkerTest(headless: true), () => runWebServiceWorkerTest(headless: true),
() => _runWebStackTraceTest('profile', 'lib/stack_trace.dart'),
() => _runWebStackTraceTest('release', 'lib/stack_trace.dart'),
() => _runWebStackTraceTest('profile', 'lib/framework_stack_trace.dart'),
() => _runWebStackTraceTest('release', 'lib/framework_stack_trace.dart'),
() => _runWebDebugTest('lib/stack_trace.dart'),
() => _runWebDebugTest('lib/framework_stack_trace.dart'),
() => _runWebDebugTest('lib/web_directory_loading.dart'),
() => _runWebDebugTest('test/test.dart'),
() => _runWebDebugTest('lib/null_assert_main.dart', enableNullSafety: true),
() => _runWebDebugTest('lib/null_safe_main.dart', enableNullSafety: true),
() => _runWebDebugTest('lib/web_define_loading.dart',
additionalArguments: <String>[
'--dart-define=test.valueA=Example,A',
'--dart-define=test.valueB=Value',
]
),
() => _runWebReleaseTest('lib/web_define_loading.dart',
additionalArguments: <String>[
'--dart-define=test.valueA=Example,A',
'--dart-define=test.valueB=Value',
]
),
() => _runWebDebugTest('lib/sound_mode.dart', additionalArguments: <String>[
'--sound-null-safety',
]),
() => _runWebReleaseTest('lib/sound_mode.dart', additionalArguments: <String>[
'--sound-null-safety',
]),
]; ];
await _ensureChromeDriverIsRunning(); await _ensureChromeDriverIsRunning();
await _runShardRunnerIndexOfTotalSubshard(tests); await _runShardRunnerIndexOfTotalSubshard(tests);
...@@ -1069,48 +1098,6 @@ Future<void> _runGalleryE2eWebTest(String buildMode, { bool canvasKit = false }) ...@@ -1069,48 +1098,6 @@ Future<void> _runGalleryE2eWebTest(String buildMode, { bool canvasKit = false })
print('${green}Integration test passed.$reset'); print('${green}Integration test passed.$reset');
} }
/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/// !!! WARNING WARNING WARNING WARNING WARNING WARNING!!!
/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
///
/// Do not put any more tests here. This shard is not properly subsharded.
/// Adding more tests here will linearly increase the runtime of the shard
/// making the overall Flutter CI build longer. Consider adding tests to
/// [_runWebLongRunningTests] instead (increasing subshard count if necessary).
///
// TODO(yjbanov): increase subshard count in _runWebLongRunningTests and retire
// this shard.
Future<void> _runWebIntegrationTests() async {
await _runWebStackTraceTest('profile', 'lib/stack_trace.dart');
await _runWebStackTraceTest('release', 'lib/stack_trace.dart');
await _runWebStackTraceTest('profile', 'lib/framework_stack_trace.dart');
await _runWebStackTraceTest('release', 'lib/framework_stack_trace.dart');
await _runWebDebugTest('lib/stack_trace.dart');
await _runWebDebugTest('lib/framework_stack_trace.dart');
await _runWebDebugTest('lib/web_directory_loading.dart');
await _runWebDebugTest('test/test.dart');
await _runWebDebugTest('lib/null_assert_main.dart', enableNullSafety: true);
await _runWebDebugTest('lib/null_safe_main.dart', enableNullSafety: true);
await _runWebDebugTest('lib/web_define_loading.dart',
additionalArguments: <String>[
'--dart-define=test.valueA=Example,A',
'--dart-define=test.valueB=Value',
]
);
await _runWebReleaseTest('lib/web_define_loading.dart',
additionalArguments: <String>[
'--dart-define=test.valueA=Example,A',
'--dart-define=test.valueB=Value',
]
);
await _runWebDebugTest('lib/sound_mode.dart', additionalArguments: <String>[
'--sound-null-safety',
]);
await _runWebReleaseTest('lib/sound_mode.dart', additionalArguments: <String>[
'--sound-null-safety',
]);
}
Future<void> _runWebStackTraceTest(String buildMode, String entrypoint) async { Future<void> _runWebStackTraceTest(String buildMode, String entrypoint) async {
final String testAppDirectory = path.join(flutterRoot, 'dev', 'integration_tests', 'web'); final String testAppDirectory = path.join(flutterRoot, 'dev', 'integration_tests', 'web');
final String appBuildDirectory = path.join(testAppDirectory, 'build', 'web'); final String appBuildDirectory = path.join(testAppDirectory, 'build', 'web');
...@@ -1137,9 +1124,13 @@ Future<void> _runWebStackTraceTest(String buildMode, String entrypoint) async { ...@@ -1137,9 +1124,13 @@ Future<void> _runWebStackTraceTest(String buildMode, String entrypoint) async {
); );
// Run the app. // Run the app.
final int serverPort = await findAvailablePort();
final int browserDebugPort = await findAvailablePort();
final String result = await evalTestAppInChrome( final String result = await evalTestAppInChrome(
appUrl: 'http://localhost:8080/index.html', appUrl: 'http://localhost:$serverPort/index.html',
appDirectory: appBuildDirectory, appDirectory: appBuildDirectory,
serverPort: serverPort,
browserDebugPort: browserDebugPort,
); );
if (result.contains('--- TEST SUCCEEDED ---')) { if (result.contains('--- TEST SUCCEEDED ---')) {
...@@ -1181,9 +1172,13 @@ Future<void> _runWebReleaseTest(String target, { ...@@ -1181,9 +1172,13 @@ Future<void> _runWebReleaseTest(String target, {
); );
// Run the app. // Run the app.
final int serverPort = await findAvailablePort();
final int browserDebugPort = await findAvailablePort();
final String result = await evalTestAppInChrome( final String result = await evalTestAppInChrome(
appUrl: 'http://localhost:8080/index.html', appUrl: 'http://localhost:$serverPort/index.html',
appDirectory: appBuildDirectory, appDirectory: appBuildDirectory,
serverPort: serverPort,
browserDebugPort: browserDebugPort,
); );
if (result.contains('--- TEST SUCCEEDED ---')) { if (result.contains('--- TEST SUCCEEDED ---')) {
......
...@@ -70,3 +70,24 @@ String prettyPrintDuration(Duration duration) { ...@@ -70,3 +70,24 @@ String prettyPrintDuration(Duration duration) {
void printProgress(String action, String workingDir, String command) { void printProgress(String action, String workingDir, String command) {
print('$clock $action: cd $cyan$workingDir$reset; $green$command$reset'); print('$clock $action: cd $cyan$workingDir$reset; $green$command$reset');
} }
int _portCounter = 8080;
/// Finds the next available local port.
Future<int> findAvailablePort() async {
while (!await _isPortAvailable(_portCounter)) {
_portCounter += 1;
}
return _portCounter++;
}
Future<bool> _isPortAvailable(int port) async {
try {
final RawSocket socket = await RawSocket.connect('localhost', port);
socket.shutdown(SocketDirection.both);
await socket.close();
return false;
} on SocketException {
return true;
}
}
...@@ -523,27 +523,33 @@ ...@@ -523,27 +523,33 @@
"flaky": false "flaky": false
}, },
{ {
"name": "Linux web_integration_tests", "name": "Linux web_long_running_tests_1_5",
"repo": "flutter", "repo": "flutter",
"task_name": "linux_web_integration_tests", "task_name": "linux_web_long_running_tests_1_5",
"flaky": false "flaky": false
}, },
{ {
"name": "Linux web_long_running_tests_1_3", "name": "Linux web_long_running_tests_2_5",
"repo": "flutter", "repo": "flutter",
"task_name": "linux_web_long_running_tests_1_3", "task_name": "linux_web_long_running_tests_2_5",
"flaky": false "flaky": false
}, },
{ {
"name": "Linux web_long_running_tests_2_3", "name": "Linux web_long_running_tests_3_5",
"repo": "flutter", "repo": "flutter",
"task_name": "linux_web_long_running_tests_2_3", "task_name": "linux_web_long_running_tests_3_5",
"flaky": false "flaky": false
}, },
{ {
"name": "Linux web_long_running_tests_3_3", "name": "Linux web_long_running_tests_4_5",
"repo": "flutter", "repo": "flutter",
"task_name": "linux_web_long_running_tests_3_3", "task_name": "linux_web_long_running_tests_4_5",
"flaky": false
},
{
"name": "Linux web_long_running_tests_5_5",
"repo": "flutter",
"task_name": "linux_web_long_running_tests_5_5",
"flaky": false "flaky": false
}, },
{ {
......
...@@ -305,37 +305,37 @@ ...@@ -305,37 +305,37 @@
"run_if": ["dev/", "packages/", "bin/"] "run_if": ["dev/", "packages/", "bin/"]
}, },
{ {
"name": "Linux web_integration_tests", "name": "Linux web_long_running_tests_1_5",
"repo": "flutter", "repo": "flutter",
"task_name": "linux_web_integration_tests", "task_name": "web_long_running_tests_1_5",
"enabled": true, "enabled": true,
"run_if": [ "run_if": ["dev/", "packages/", "bin/"]
"dev/", },
"packages/flutter/", {
"packages/flutter_test/", "name": "Linux web_long_running_tests_2_5",
"packages/flutter_tools/", "repo": "flutter",
"packages/flutter_web_plugins/", "task_name": "web_long_running_tests_2_5",
"bin/" "enabled": true,
] "run_if": ["dev/", "packages/", "bin/"]
}, },
{ {
"name": "Linux web_long_running_tests_1_3", "name": "Linux web_long_running_tests_3_5",
"repo": "flutter", "repo": "flutter",
"task_name": "web_long_running_tests_1_3", "task_name": "web_long_running_tests_3_5",
"enabled": true, "enabled": true,
"run_if": ["dev/", "packages/", "bin/"] "run_if": ["dev/", "packages/", "bin/"]
}, },
{ {
"name": "Linux web_long_running_tests_2_3", "name": "Linux web_long_running_tests_4_5",
"repo": "flutter", "repo": "flutter",
"task_name": "web_long_running_tests_2_3", "task_name": "web_long_running_tests_4_5",
"enabled": true, "enabled": true,
"run_if": ["dev/", "packages/", "bin/"] "run_if": ["dev/", "packages/", "bin/"]
}, },
{ {
"name": "Linux web_long_running_tests_3_3", "name": "Linux web_long_running_tests_5_5",
"repo": "flutter", "repo": "flutter",
"task_name": "web_long_running_tests_1_3", "task_name": "web_long_running_tests_5_5",
"enabled": true, "enabled": true,
"run_if": ["dev/", "packages/", "bin/"] "run_if": ["dev/", "packages/", "bin/"]
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment