Revert "Clean up test infrastructure (#41880)" (#42982)
This reverts commit 1781d5c9bbb4a1b408e40bd40e433c3541bb68fc.
diff --git a/.cirrus.yml b/.cirrus.yml
index 3b380f3..9eb90de 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,41 +1,18 @@
-# CIRRUS CONFIGURATION FILE
+container:
+ image: gcr.io/flutter-cirrus/build-flutter-image:latest
-use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
-
-environment:
- # For details about environment variables used in Cirrus, including how encrypted variables work,
- # see https://cirrus-ci.org/guide/writing-tasks/#environment-variables
- GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
- # We change Flutter's directory to include a space in its name (see $CIRRUS_WORKING_DIR) so that
- # we constantly test path names with spaces in them. The FLUTTER_SDK_PATH_WITH_SPACE variable must
- # therefore have a space in it.
- FLUTTER_SDK_PATH_WITH_SPACE: "flutter sdk"
- # We force BOT to true so that all our tools know we're in a CI environment. This avoids any
- # dependency on precisely how Cirrus is detected by our tools.
- BOT: "true"
- # Unsetting CIRRUS_CHANGE_MESSAGE and CIRRUS_COMMIT_MESSAGE as they might include non-ASCII
- # characters which makes Gradle crash. See: https://github.com/flutter/flutter/issues/24935
- # TODO(amirha): remove once we've migrated to newer Gradle
- CIRRUS_CHANGE_MESSAGE: ""
- CIRRUS_COMMIT_MESSAGE: ""
-
-# LINUX SHARDS
task:
- container:
- image: gcr.io/flutter-cirrus/build-flutter-image:latest
- cpu: $CPU
- memory: $MEMORY
- environment:
- # We shrink our default resource requirement as much as possible because that way we are more
- # likely to get scheduled. We require 4G of RAM because most of the shards (all but one as of
- # October 2019) just get OOM-killed with less. Some shards may need more. When increasing the
- # requirements for select shards, please leave a comment on those shards saying when you
- # increased the requirements, what numbers you tried, and what the results were.
- CPU: 1 # 0.1-8 without compute credits, 0.1-30 with (yes, you can go fractional)
- MEMORY: 4G # 256M-24G without compute credits, 256M-90G with
- CIRRUS_WORKING_DIR: "/tmp/$FLUTTER_SDK_PATH_WITH_SPACE"
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ env:
+ # Name the SDK directory to include a space so that we constantly
+ # test path names with spaces in them.
+ CIRRUS_WORKING_DIR: "/tmp/flutter sdk"
PATH: "$CIRRUS_WORKING_DIR/bin:$CIRRUS_WORKING_DIR/bin/cache/dart-sdk/bin:$PATH"
ANDROID_SDK_ROOT: "/opt/android_sdk"
+ git_fetch_script:
+ - git clean -xfd
+ - git fetch origin
+ - git fetch origin master # To set FETCH_HEAD for "git merge-base" to work
pub_cache:
folder: $HOME/.pub-cache
fingerprint_script: echo $OS; grep -r --include=pubspec.yaml 'PUBSPEC CHECKSUM' "$CIRRUS_WORKING_DIR"
@@ -45,302 +22,345 @@
artifacts_cache:
folder: bin/cache/artifacts
fingerprint_script: echo $OS; cat bin/internal/*.version
- setup_script:
- - date
- - git clean -xffd
- - git fetch origin
- - git fetch origin master # To set FETCH_HEAD, so that "git merge-base" works.
- - flutter config --no-analytics
- - flutter doctor -v
- - flutter update-packages
- - ./dev/bots/accept_android_sdk_licenses.sh
- - date
- on_failure:
- failure_script:
- - date
- - which flutter
+ setup_script: ./dev/bots/cirrus_setup.sh
matrix:
- - name: analyze-linux # linux-only
- # environment:
- # Empirically, the analyze-linux shard runs surprisingly fast (under 15 minutes) with just 1
- # CPU and 4G RAM as of October 2019. It fails with less than 4G though.
- script:
- - dart --enable-asserts ./dev/bots/analyze.dart
-
- - name: framework_tests-widgets-linux
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # We use 3 CPUs because that's the minimum required to get framework_tests-widgets-linux
- # running fast enough that it is not the long pole, as of OCtober 2019.
- CPU: 3
- GOLDCTL: "$CIRRUS_WORKING_DIR/depot_tools/goldctl"
- GOLD_SERVICE_ACCOUNT: ENCRYPTED[3afeea5ac7201151c3d0dc9648862f0462b5e4f55dc600ca8b692319622f7c3eda3d577b1b16cc2ef0311b7314c1c095]
- script:
- - ./dev/bots/download_goldctl.sh
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: framework_tests-libraries-linux
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # We use 3 CPUs because that's the minimum required to get the
- # framework_tests-libraries-linux shard running fast enough that it is not the long pole, as
- # of October 2019.
- CPU: 3
- GOLDCTL: "$CIRRUS_WORKING_DIR/depot_tools/goldctl"
- GOLD_SERVICE_ACCOUNT: ENCRYPTED[3afeea5ac7201151c3d0dc9648862f0462b5e4f55dc600ca8b692319622f7c3eda3d577b1b16cc2ef0311b7314c1c095]
- script:
- - ./dev/bots/download_goldctl.sh
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: framework_tests-misc-linux
- # this includes the tests for directories in dev/
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # We use 3 CPUs because that's the minimum required to get framework_tests-misc-linux
- # running fast enough that it is not the long pole, as of October 2019.
- CPU: 3
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: tool_tests-general-linux
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # As of October 2019, the tool_tests-general-linux shard got faster with more CPUs up to 4
- # CPUs, and needed at least 8G of RAM to not run out of memory.
- CPU: 4
- MEMORY: 8G
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: tool_tests-commands-linux
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # As of October 2019, the tool_tests-commands-linux shard got faster with more CPUs up to 6
- # CPUs, and needed at least 8G of RAM to not run out of memory.
- CPU: 6
- MEMORY: 8G
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: tool_tests-integration-linux
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # As of October 2019, the tool_tests-integration-linux shard got faster with more CPUs up to
- # 6 CPUs, and needed at least 8G of RAM to not run out of memory.
- CPU: 6
- MEMORY: 8G
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: tool_coverage-linux # linux-only
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**/*.dart', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # As of October 2019, the tool_coverage-linux shard needed at least 12G of RAM to run without
- # getting OOM-killed, and even 8 CPUs took 25 minutes.
- CPU: 8
- MEMORY: 12G
- CODECOV_TOKEN: ENCRYPTED[7c76a7f8c9264f3b7f3fd63fcf186f93c62c4dfe43ec288861c2f506d456681032b89efe7b7a139c82156350ca2c752c]
- script:
- - dart --enable-asserts ./dev/bots/test.dart
- - bash <(curl -s https://codecov.io/bash) -c -f packages/flutter_tools/coverage/lcov.info -F flutter_tool
-
- - name: web_tests-0-linux
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'packages/flutter_web_plugins/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # As of October 2019, the Web shards needed more than 6G of RAM.
- CPU: 2
- MEMORY: 8G
- allow_failures: true
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: web_tests-1-linux
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'packages/flutter_web_plugins/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # As of October 2019, the Web shards needed more than 6G of RAM.
- CPU: 2
- MEMORY: 8G
- allow_failures: true
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: web_tests-2-linux
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'packages/flutter_web_plugins/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # As of October 2019, the Web shards needed more than 6G of RAM.
- CPU: 2
- MEMORY: 8G
- allow_failures: true
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: web_tests-3-linux
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'packages/flutter_web_plugins/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # As of October 2019, the Web shards needed more than 6G of RAM.
- CPU: 2
- MEMORY: 8G
- allow_failures: true
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: web_tests-4-linux
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'packages/flutter_web_plugins/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # As of October 2019, the Web shards needed more than 6G of RAM.
- CPU: 2
- MEMORY: 8G
- allow_failures: true
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: web_tests-5_last-linux # last Web shard must end with _last
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'packages/flutter_web_plugins/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # As of October 2019, the Web shards needed more than 6G of RAM.
- CPU: 2
- MEMORY: 8G
- allow_failures: true
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: build_tests-linux
- environment:
- # With 1 CPU and 4G of RAM, as of October 2019, build_tests-linux would get OOM-killed.
- # Increasing the RAM to 12G allowed it to finish in about 30 minutes, any extra CPU (tried 2
- # and 4) reduced that to just over 20 minutes. 6G was enough not to get OOM-killed.
- CPU: 2
- MEMORY: 6G
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-0-linux
- environment:
- # Some of the host-only devicelab tests are pretty involved and need a lot of RAM.
- CPU: 2
- MEMORY: 8G
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-1-linux
- environment:
- # Some of the host-only devicelab tests are pretty involved and need a lot of RAM.
- CPU: 2
- MEMORY: 8G
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-2-linux
- environment:
- # Some of the host-only devicelab tests are pretty involved and need a lot of RAM.
- CPU: 2
- MEMORY: 8G
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-3-linux
- environment:
- # Some of the host-only devicelab tests are pretty involved and need a lot of RAM.
- CPU: 2
- MEMORY: 8G
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-4-linux
- environment:
- # Some of the host-only devicelab tests are pretty involved and need a lot of RAM.
- CPU: 2
- MEMORY: 8G
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-5_last-linux
- environment:
- # Some of the host-only devicelab tests are pretty involved and need a lot of RAM.
- CPU: 2
- MEMORY: 8G
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- # TODO(ianh): name: add_to_app_tests-linux
-
- - name: docs-linux # linux-only
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_drive/**', 'packages/flutter_localizations/**', 'packages/flutter_goldens/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
- # Empirically, as of October 2019, the docs-linux shard took about 30 minutes when run with
- # 1 CPU and 4G of RAM. 2 CPUs reduced that to 20 minutes, more CPUs did not improve matters.
- CPU: 2
+ - name: docs
+ skip: "!changesInclude('dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_drive/**', 'packages/flutter_localizations/**', 'packages/flutter_goldens/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master'"
+ env:
+ SHARD: docs
# For uploading master docs to Firebase master branch staging site
FIREBASE_MASTER_TOKEN: ENCRYPTED[eb768d18798fdc5abfe09b224e1724c4d82831d715ccf90df2c79d618c317216cbd99493278361f6fe7948b409b603f0]
# For uploading beta docs to Firebase public live site
FIREBASE_PUBLIC_TOKEN: ENCRYPTED[37e8b82f167864cae9a3f4d2cf3f37dea331d9375c295327c45de524f6c588fa6f6d63e5784f10f6d43ce29689f36c92]
- script:
- - ./dev/bots/docs.sh
-
+ docs_script: ./dev/bots/docs.sh
+ - name: deploy_gallery
+ depends_on:
+ - docs
+ - analyze
+ - build_tests-linux
+ env:
+ SHARD: deploy_gallery
+ GOOGLE_DEVELOPER_SERVICE_ACCOUNT_ACTOR_FASTLANE: ENCRYPTED[d9ac1462c3c556fc2f8165c9d5566a16497d8ebc38a50357f7f3abf136b7f83e1d1d76dde36fee356cb0f9ebf7a89346]
+ ANDROID_GALLERY_UPLOAD_KEY: ENCRYPTED[0f2aca35f05b26add5d9edea2a7449341269a2b7e22d5c667f876996e2e8bc44ff1369431ebf73b7c5581fd95d0e5902]
+ test_script:
+ # Unsetting CIRRUS_CHANGE_MESSAGE and CIRRUS_COMMIT_MESSAGE as they
+ # might include non-ASCII characters which makes Gradle crash.
+ # See: https://github.com/flutter/flutter/issues/24935
+ # This is a temporary workaround until we figure how to properly configure
+ # a UTF8 locale on Cirrus (or until the Gradle bug is fixed).
+ # TODO(amirh): Set the locale to UTF8.
+ - echo "$CIRRUS_CHANGE_MESSAGE" > /tmp/cirrus_change_message.txt
+ - echo "$CIRRUS_COMMIT_MESSAGE" > /tmp/cirrus_commit_message.txt
+ - export CIRRUS_CHANGE_MESSAGE=""
+ - export CIRRUS_COMMIT_MESSAGE=""
+ - ./dev/bots/deploy_gallery.sh
+ - export CIRRUS_CHANGE_MESSAGE=`cat /tmp/cirrus_change_message.txt`
+ - export CIRRUS_COMMIT_MESSAGE=`cat /tmp/cirrus_commit_message.txt`
+ - name: analyze
+ test_script:
+ - dart --enable-asserts ./dev/bots/analyze.dart
+ - name: bots_tests-linux
+ skip: "!changesInclude('dev/bots/**')"
+ test_script:
+ - (cd ./dev/bots && pub run test)
+ container:
+ cpu: 4
+ memory: 12G
+ - name: tests_widgets-linux
+ skip: "!changesInclude('dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tests
+ SUBSHARD: widgets
+ GOLDCTL: "$CIRRUS_WORKING_DIR/depot_tools/goldctl"
+ GOLD_SERVICE_ACCOUNT: ENCRYPTED[3afeea5ac7201151c3d0dc9648862f0462b5e4f55dc600ca8b692319622f7c3eda3d577b1b16cc2ef0311b7314c1c095]
+ goldctl_script: ./dev/bots/download_goldctl.sh
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: tests_framework_other-linux
+ skip: "!changesInclude('dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tests
+ SUBSHARD: framework_other
+ GOLDCTL: "$CIRRUS_WORKING_DIR/depot_tools/goldctl"
+ GOLD_SERVICE_ACCOUNT: ENCRYPTED[3afeea5ac7201151c3d0dc9648862f0462b5e4f55dc600ca8b692319622f7c3eda3d577b1b16cc2ef0311b7314c1c095]
+ goldctl_script: ./dev/bots/download_goldctl.sh
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: tests_extras-linux
+ skip: "!changesInclude('dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**', 'dev/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tests
+ SUBSHARD: extras
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ # all of the tests except the ones in test/integration and test/commands/create_test for packages/flutter_tools
+ - name: tool_tests_general-linux
+ skip: "!changesInclude('dev/**', 'packages/flutter_tools/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tool_tests
+ SUBSHARD: general
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: tool_tests_commands-linux
+ skip: "!changesInclude('dev/**', 'packages/flutter_tools/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tool_tests
+ SUBSHARD: commands
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ # all of the tests in test/integration for packages/flutter_tools
+ - name: tool_tests_integration-linux
+ skip: "!changesInclude('dev/**', 'packages/flutter_tools/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tool_tests
+ SUBSHARD: integration
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: tool_coverage-linux
+ skip: "!changesInclude('dev/**', 'packages/flutter_tools/**/*.dart') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ CODECOV_TOKEN: ENCRYPTED[7c76a7f8c9264f3b7f3fd63fcf186f93c62c4dfe43ec288861c2f506d456681032b89efe7b7a139c82156350ca2c752c]
+ SHARD: tool_coverage
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ - bash <(curl -s https://codecov.io/bash) -c -s ./packages/flutter_tools/coverage/ -f '*.lcov.info' -F flutter_tool
+ container:
+ cpu: 8
+ memory: 24G
+ - name: web_tests-linux-shard-0
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ env:
+ SHARD: web_tests
+ WEB_SHARD: 0
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: web_tests-linux-shard-1
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ env:
+ SHARD: web_tests
+ WEB_SHARD: 1
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: web_tests-linux-shard-2
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ env:
+ SHARD: web_tests
+ WEB_SHARD: 2
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: web_tests-linux-shard-3
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ env:
+ SHARD: web_tests
+ WEB_SHARD: 3
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: web_tests-linux-shard-4
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ env:
+ SHARD: web_tests
+ WEB_SHARD: 4
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: web_tests-linux-shard-5
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ env:
+ SHARD: web_tests
+ WEB_SHARD: 5
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: build_tests-linux
+ env:
+ SHARD: build_tests
+ - name: integration_tests-linux
+ env:
+ SHARD: integration_tests
+ test_script:
+ # Unsetting CIRRUS_CHANGE_MESSAGE and CIRRUS_COMMIT_MESSAGE as they
+ # might include non-ASCII characters which makes Gradle crash.
+ # See: https://github.com/flutter/flutter/issues/24935
+ # This is a temporary workaround until we figure how to properly configure
+ # a UTF8 locale on Cirrus (or until the Gradle bug is fixed).
+ # TODO(amirh): Set the locale to UTF8.
+ - echo "$CIRRUS_CHANGE_MESSAGE" > /tmp/cirrus_change_message.txt
+ - echo "$CIRRUS_COMMIT_MESSAGE" > /tmp/cirrus_commit_message.txt
+ - export CIRRUS_CHANGE_MESSAGE=""
+ - export CIRRUS_COMMIT_MESSAGE=""
+ - dart --enable-asserts ./dev/bots/test.dart
+ - export CIRRUS_CHANGE_MESSAGE=`cat /tmp/cirrus_change_message.txt`
+ - export CIRRUS_COMMIT_MESSAGE=`cat /tmp/cirrus_commit_message.txt`
+ container:
+ cpu: 4
+ memory: 12G
+ - name: gradle_tests-linux-shard-1
+ env:
+ SHARD: integration_tests
+ SUBSHARD: gradle1
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: gradle_tests-linux-shard-2
+ env:
+ SHARD: integration_tests
+ SUBSHARD: gradle2
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: gradle_embedding_v2_tests-linux-shard-1
+ env:
+ SHARD: integration_tests
+ SUBSHARD: gradle1
+ ENABLE_ANDROID_EMBEDDING_V2: 'true'
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: gradle_embedding_v2_tests-linux-shard-2
+ env:
+ SHARD: integration_tests
+ SUBSHARD: gradle2
+ ENABLE_ANDROID_EMBEDDING_V2: 'true'
+ test_script:
+ - dart --enable-asserts ./dev/bots/test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: release_smoke_tests
+ env:
+ CLOUDSDK_CORE_DISABLE_PROMPTS: 1
+ GCLOUD_FIREBASE_TESTLAB_KEY: ENCRYPTED[1c140257edc48f5578fa5a0e5038b84c8e53270c405efa5a8e35ea303a4e0d135853989f448f72136206de854d17fbec]
+ test_script:
+ - echo "$CIRRUS_CHANGE_MESSAGE" > /tmp/cirrus_change_message.txt
+ - echo "$CIRRUS_COMMIT_MESSAGE" > /tmp/cirrus_commit_message.txt
+ - export CIRRUS_CHANGE_MESSAGE=""
+ - export CIRRUS_COMMIT_MESSAGE=""
+ - ./dev/bots/firebase_testlab.sh
+ - export CIRRUS_CHANGE_MESSAGE=`cat /tmp/cirrus_change_message.txt`
+ - export CIRRUS_COMMIT_MESSAGE=`cat /tmp/cirrus_commit_message.txt`
- name: customer_testing-linux
- # environment:
- # Empirically, this shard runs fine at 1 CPU and 4G RAM as of October 2019. We will probably
- # want to grow this container when we invite people to add their tests in large numbers.
script:
- rm -rf bin/cache/pkg/tests
- git clone https://github.com/flutter/tests.git bin/cache/pkg/tests
- dart --enable-asserts dev/customer_testing/run_tests.dart --skip-on-fetch-failure --skip-template bin/cache/pkg/tests/registry/*.test
- - name: firebase_test_lab_tests-linux # linux-only
- environment:
- # Empirically, this shard runs in 20-25 minutes with just one CPU and 4G of RAM, as of
- # October 2019. It does not seem to be sensitive to the number of CPUs or amount of RAM;
- # doubling CPUs had no effect (mere seconds under 20 minutes), increasing RAM to 24G left it
- # on the high end of the 20-25 minute range. (This makes sense, as it's just driving the
- # Firebase test lab remotely.) Less than 4G of RAM made it go OOM.
- CLOUDSDK_CORE_DISABLE_PROMPTS: 1
- GCLOUD_FIREBASE_TESTLAB_KEY: ENCRYPTED[1c140257edc48f5578fa5a0e5038b84c8e53270c405efa5a8e35ea303a4e0d135853989f448f72136206de854d17fbec]
- script:
- - ./dev/bots/firebase_testlab.sh
-
- - name: deploy_gallery-linux # linux- and macos- only
- depends_on:
- - analyze-linux
- - framework_tests-widgets-linux
- - framework_tests-libraries-linux
- - framework_tests-misc-linux
- - tool_tests-general-linux
- - tool_tests-commands-linux
- - tool_tests-integration-linux
- - build_tests-linux
- - hostonly_devicelab_tests-0-linux
- - hostonly_devicelab_tests-1-linux
- - hostonly_devicelab_tests-2-linux
- - hostonly_devicelab_tests-3-linux
- - hostonly_devicelab_tests-4-linux
- - hostonly_devicelab_tests-5_last-linux
- - firebase_test_lab_tests-linux
- environment:
- # As of October 2019, 1 CPU and 4G of RAM let deploy_gallery-linux finish in about 15
- # minutes, once it got started.
- GOOGLE_DEVELOPER_SERVICE_ACCOUNT_ACTOR_FASTLANE: ENCRYPTED[d9ac1462c3c556fc2f8165c9d5566a16497d8ebc38a50357f7f3abf136b7f83e1d1d76dde36fee356cb0f9ebf7a89346]
- ANDROID_GALLERY_UPLOAD_KEY: ENCRYPTED[0f2aca35f05b26add5d9edea2a7449341269a2b7e22d5c667f876996e2e8bc44ff1369431ebf73b7c5581fd95d0e5902]
- script:
- - ./dev/bots/deploy_gallery.sh
-
-# WINDOWS SHARDS
task:
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
windows_container:
image: cirrusci/android-sdk:28-windowsservercore-2019
os_version: 2019
- cpu: $CPU
- memory: $MEMORY
- environment:
- # It's not clear that changing the cpu/memory fields here has any impact, so we use
- # small numbers...
- CPU: 2 # 1-8 without compute credits, 1-30 with
- MEMORY: 2G # 256M-24G without compute credits, 256M-90G with
- CIRRUS_WORKING_DIR: "C:\\Windows\\Temp\\$FLUTTER_SDK_PATH_WITH_SPACE"
+ cpu: 4
+ env:
+ CIRRUS_WORKING_DIR: "C:\\Windows\\Temp\\flutter sdk"
PATH: "$CIRRUS_WORKING_DIR/bin;$CIRRUS_WORKING_DIR/bin/cache/dart-sdk/bin;$PATH"
+ git_fetch_script:
+ - git clean -xfd
+ - git fetch origin
+ - git fetch origin master # To set FETCH_HEAD for "git merge-base" to work
pub_cache:
folder: $APPDATA\Pub\Cache
fingerprint_script:
- - ps: $Environment:OS; Get-ChildItem -Path "$Environment:CIRRUS_WORKING_DIR" pubspec.yaml -Recurse | Select-String -Pattern "PUBSPEC CHECKSUM" -SimpleMatch
+ - ps: $Env:OS; Get-ChildItem -Path "$Env:CIRRUS_WORKING_DIR" pubspec.yaml -Recurse | Select-String -Pattern "PUBSPEC CHECKSUM" -SimpleMatch
+ flutter_pkg_cache:
+ folder: bin\cache\pkg
+ fingerprint_script: echo %OS% & type bin\internal\*.version
+ artifacts_cache:
+ folder: bin\cache\artifacts
+ fingerprint_script: echo %OS% & type bin\internal\engine.version
+ setup_script:
+ - flutter config --no-analytics
+ - flutter doctor -v
+ - flutter update-packages
+ - git fetch origin master
+ test_all_script:
+ - dart --enable-asserts dev\bots\test.dart
+ matrix:
+ # all of the tests except test/integration and test/commands/create_test for packages/flutter_tools
+ - name: tool_tests_general-windows
+ skip: "!changesInclude('dev/**', 'packages/flutter_tools/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tool_tests
+ SUBSHARD: general
+ # all of the tests in test/commands/create_test
+ - name: tool_tests_commands-windows
+ skip: "!changesInclude('dev/**', 'packages/flutter_tools/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tool_tests
+ SUBSHARD: commands
+ # all of the tests in test/integration for packages/flutter_tools
+ - name: tool_tests_integration-windows
+ skip: "!changesInclude('dev/**', 'packages/flutter_tools/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tool_tests
+ SUBSHARD: integration
+
+task:
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ windows_container:
+ image: cirrusci/android-sdk:28-windowsservercore-2019
+ os_version: 2019
+ cpu: 4
+ env:
+ CIRRUS_WORKING_DIR: "C:\\Windows\\Temp\\flutter sdk"
+ PATH: "$CIRRUS_WORKING_DIR/bin;$CIRRUS_WORKING_DIR/bin/cache/dart-sdk/bin;$PATH"
+ git_fetch_script:
+ - git clean -xfd
+ - git fetch origin
+ - git fetch origin master # To set FETCH_HEAD for "git merge-base" to work
+ pub_cache:
+ folder: $APPDATA\Pub\Cache
+ fingerprint_script:
+ - ps: $Env:OS; Get-ChildItem -Path "$Env:CIRRUS_WORKING_DIR" pubspec.yaml -Recurse | Select-String -Pattern "PUBSPEC CHECKSUM" -SimpleMatch
flutter_pkg_cache:
folder: bin\cache\pkg
fingerprint_script: echo %OS% & type bin\internal\*.version
@@ -348,285 +368,290 @@
folder: bin\cache\artifacts
fingerprint_script: echo %OS% & type bin\internal\*.version
setup_script:
- - git clean -xffd
- - git fetch origin
- - git fetch origin master # To set FETCH_HEAD, so that "git merge-base" works.
- flutter config --no-analytics
- flutter doctor -v
- flutter update-packages
- git fetch origin master
matrix:
- - name: framework_tests-widgets-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
+ - name: bots_tests-windows
+ skip: "!changesInclude('dev/bots/**')"
+ test_script:
+ - cd dev\bots
+ - pub run test
+ - name: tests_widgets-windows
+ skip: "!changesInclude('dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tests
+ SUBSHARD: widgets
GOLDCTL: "C:\\Windows\\Temp\\depot_tools\\goldctl.exe"
GOLD_SERVICE_ACCOUNT: ENCRYPTED[3afeea5ac7201151c3d0dc9648862f0462b5e4f55dc600ca8b692319622f7c3eda3d577b1b16cc2ef0311b7314c1c095]
- script:
- - powershell dev\bots\download_goldctl.ps1
+ goldctl_script: powershell dev\bots\download_goldctl.ps1
+ test_all_script:
- dart --enable-asserts dev\bots\test.dart
-
- - name: framework_tests-libraries-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
+ - name: tests_framework_other-windows
+ skip: "!changesInclude('dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tests
+ SUBSHARD: framework_other
GOLDCTL: "C:\\Windows\\Temp\\depot_tools\\goldctl.exe"
GOLD_SERVICE_ACCOUNT: ENCRYPTED[3afeea5ac7201151c3d0dc9648862f0462b5e4f55dc600ca8b692319622f7c3eda3d577b1b16cc2ef0311b7314c1c095]
- script:
- - powershell dev\bots\download_goldctl.ps1
+ goldctl_script: powershell dev\bots\download_goldctl.ps1
+ test_all_script:
- dart --enable-asserts dev\bots\test.dart
-
- - name: framework_tests-misc-windows
- # this includes the tests for directories in dev/
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- script:
+ - name: tests_extras-windows
+ skip: "!changesInclude('dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**', 'dev/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tests
+ SUBSHARD: extras
+ test_all_script:
- dart --enable-asserts dev\bots\test.dart
-
- - name: tool_tests-general-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: tool_tests-commands-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: tool_tests-integration-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- # TODO(ianh): Enable Web tests on Windows
-
- name: build_tests-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941
- script:
+ env:
+ SHARD: build_tests
+ container:
+ cpu: 4
+ memory: 12G
+ test_all_script:
- dart --enable-asserts dev\bots\test.dart
-
- - name: hostonly_devicelab_tests-0-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-1-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-2-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-3-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-4-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-5_last-windows
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- # TODO(ianh): name: add_to_app_tests-windows
-
+ - name: integration_tests-windows
+ env:
+ SHARD: integration_tests
+ container:
+ cpu: 4
+ memory: 12G
+ test_all_script:
+ - dart --enable-asserts dev\bots\test.dart
- name: customer_testing-windows
- script:
+ test_script:
- CMD /S /C "IF EXIST "bin\cache\pkg\tests\" RMDIR /S /Q bin\cache\pkg\tests"
- git clone https://github.com/flutter/tests.git bin\cache\pkg\tests
- dart --enable-asserts dev\customer_testing\run_tests.dart --skip-on-fetch-failure --skip-template bin/cache/pkg/tests/registry/*.test
+ - name: gradle_tests-windows-shard-1
+ env:
+ SHARD: integration_tests
+ SUBSHARD: gradle1
+ test_script:
+ - dart --enable-asserts dev\bots\test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: gradle_tests-windows-shard-2
+ env:
+ SHARD: integration_tests
+ SUBSHARD: gradle2
+ test_script:
+ - dart --enable-asserts dev\bots\test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: gradle_embedding_v2_tests-windows-shard-1
+ env:
+ SHARD: integration_tests
+ SUBSHARD: gradle1
+ ENABLE_ANDROID_EMBEDDING_V2: 'true'
+ test_script:
+ - dart --enable-asserts dev\bots\test.dart
+ container:
+ cpu: 4
+ memory: 12G
+ - name: gradle_embedding_v2_tests-windows-shard-2
+ env:
+ SHARD: integration_tests
+ SUBSHARD: gradle2
+ ENABLE_ANDROID_EMBEDDING_V2: 'true'
+ test_script:
+ - dart --enable-asserts dev\bots\test.dart
+ container:
+ cpu: 4
+ memory: 12G
-# MACOS SHARDS
-# Mac doesn't use caches because they apparently take longer to populate and save
-# than just fetching the data in the first place.
task:
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ name: deploy_gallery-macos
+ depends_on:
+ - analyze
+ env:
+ # Name the SDK directory to include a space so that we constantly
+ # test path names with spaces in them.
+ CIRRUS_WORKING_DIR: "/tmp/flutter sdk"
+ SHARD: deploy_gallery
+ # Apple Fastlane password.
+ FASTLANE_PASSWORD: ENCRYPTED[4b1f0b8d52874e9de965acd46c79743f3b81f3a513614179b9be7cf53dc8258753e257bdadb11a298ee455259df21865]
+ # Private repo for publishing certificates.
+ PUBLISHING_MATCH_CERTIFICATE_REPO: ENCRYPTED[3c0e78877d933fc80107aa6f3790fd1cf927250b852d6cb53202be696b4903ed8ca839b809626aaf18050bf7e436fab7]
+ PUBLISHING_MATCH_REPO_TOKEN: ENCRYPTED[3d1230b744c6ed6c788a91bec741b769401dbcd426b18f9af8080bfeefdfc21913ca4047980c5b5b7ce823f12e7b6b19]
+ # Apple Certificates Match Passphrase
+ MATCH_PASSWORD: ENCRYPTED[db07f252234397090e3ec59152d9ec1831f5ecd0ef97d247b1dca757bbb9ef9b7c832a39bce2caf1949ccdf097e59a73]
osx_instance:
- image: mojave-xcode-10.2-flutter # see https://cirrus-ci.org/guide/macOS/ for list of images (we should update regularly)
- # cpu is always 2
- # memory is always 8G
- environment:
- CIRRUS_WORKING_DIR: "/tmp/$FLUTTER_SDK_PATH_WITH_SPACE"
- FLUTTER_FRAMEWORK_DIR: "$CIRRUS_WORKING_DIR/bin/cache/artifacts/engine/ios/"
- PATH: "$CIRRUS_WORKING_DIR/bin:$CIRRUS_WORKING_DIR/bin/cache/dart-sdk/bin:$PATH"
- COCOAPODS_DISABLE_STATS: true
- CPU: 2
- MEMORY: 8G
- setup_script:
+ image: mojave-xcode-10.2
+ # occasionally the clock on these machines is out of sync
+ # with the actual time - this should help to verify
+ print_date_script:
- date
- - which flutter
- - sudo gem install cocoapods
- - sudo gem install xcpretty
- - git clean -xffd
+ install_cocoapods_script:
+ - sudo gem install cocoapods --no-document
+ git_fetch_script:
+ - git clean -xfd
- git fetch origin
- - git fetch origin master # To set FETCH_HEAD, so that "git merge-base" works.
- - flutter config --no-analytics
- - flutter doctor -v
- - flutter update-packages
+ - git fetch origin master # To set FETCH_HEAD
+ setup_script:
+ - bin/flutter config --no-analytics
+ - bin/flutter update-packages
+ test_all_script:
+ - ./dev/bots/deploy_gallery.sh
+
+task:
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ osx_instance:
+ image: mojave-xcode-10.2
+ depends_on:
+ - analyze
+ env:
+ CIRRUS_WORKING_DIR: "/tmp/flutter sdk"
+ COCOAPODS_DISABLE_STATS: true
+ print_date_script:
- date
- - which flutter
- on_failure:
- failure_script:
- - date
- - which flutter
+ git_fetch_script:
+ - git clean -xfd
+ - git fetch origin
+ - git fetch origin master # To set FETCH_HEAD for "git merge-base" to work
+ setup_script:
+ - bin/flutter config --no-analytics
+ - bin/flutter doctor -v
+ - bin/flutter update-packages
+ test_all_script:
+ - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
+ - bin/cache/dart-sdk/bin/dart --enable-asserts dev/bots/test.dart
matrix:
- - name: framework_tests-widgets-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
+ # all of the tests except test/integration and test/commands/create_test for packages/flutter_tools
+ - name: tool_tests_general-macos
+ skip: "!changesInclude('dev/**', 'packages/flutter_tools/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tool_tests
+ SUBSHARD: general
+ # all of the tests in test/commands/create_test
+ - name: tool_tests_commands-macos
+ skip: "!changesInclude('dev/**', 'packages/flutter_tools/**', 'bin/internal/**') && $CIRRUS_BRANCH != 'master' && $CIRRUS_BRANCH != 'stable' && $CIRRUS_BRANCH != 'beta' && $CIRRUS_BRANCH != 'dev'"
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tool_tests
+ SUBSHARD: commands
+ # all of the tests in test/integration for packages/flutter_tools
+ - name: tool_tests_integration-macos
+ only_if: $CIRRUS_BRANCH == 'master'
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tool_tests
+ SUBSHARD: integration
+
+task:
+ use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+ osx_instance:
+ image: mojave-xcode-10.2
+ depends_on:
+ - analyze
+ env:
+ CIRRUS_WORKING_DIR: "/tmp/flutter sdk"
+ COCOAPODS_DISABLE_STATS: true
+ PATH: "$CIRRUS_WORKING_DIR/bin:$CIRRUS_WORKING_DIR/bin/cache/dart-sdk/bin:$PATH"
+ # occasionally the clock on these machines is out of sync
+ # with the actual time - this should help to verify
+ print_date_script:
+ - date
+ install_cocoapods_script:
+ - sudo gem install cocoapods --no-document
+ git_fetch_script:
+ - git clean -xfd
+ - git fetch origin
+ - git fetch origin master # To set FETCH_HEAD for "git merge-base" to work
+ setup_script:
+ - bin/flutter config --no-analytics
+ - bin/flutter doctor -v
+ - bin/flutter update-packages
+ matrix:
+ - name: bots_tests-macos
+ skip: "!changesInclude('dev/bots/**')"
+ test_script:
+ - (cd ./dev/bots && pub run test)
+ - name: tests_widgets-macos
+ only_if: $CIRRUS_BRANCH == 'master'
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tests
+ SUBSHARD: widgets
GOLDCTL: "$CIRRUS_WORKING_DIR/depot_tools/goldctl"
GOLD_SERVICE_ACCOUNT: ENCRYPTED[3afeea5ac7201151c3d0dc9648862f0462b5e4f55dc600ca8b692319622f7c3eda3d577b1b16cc2ef0311b7314c1c095]
- script:
+ goldctl_script: ./dev/bots/download_goldctl.sh
+ test_all_script:
- ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - ./dev/bots/download_goldctl.sh
- dart --enable-asserts dev/bots/test.dart
-
- - name: framework_tests-libraries-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- environment:
+ on_failure:
+ print_failure_time_script: date
+ - name: tests_framework_other-macos
+ only_if: $CIRRUS_BRANCH == 'master'
+ env:
+ GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
+ SHARD: tests
+ SUBSHARD: framework_other
GOLDCTL: "$CIRRUS_WORKING_DIR/depot_tools/goldctl"
GOLD_SERVICE_ACCOUNT: ENCRYPTED[3afeea5ac7201151c3d0dc9648862f0462b5e4f55dc600ca8b692319622f7c3eda3d577b1b16cc2ef0311b7314c1c095]
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - ./dev/bots/download_goldctl.sh
- - dart --enable-asserts dev/bots/test.dart
-
- - name: framework_tests-misc-macos
- # this includes the tests for directories in dev/
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- script:
+ goldctl_script: ./dev/bots/download_goldctl.sh
+ test_all_script:
- ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- dart --enable-asserts dev/bots/test.dart
-
- - name: tool_tests-general-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: tool_tests-commands-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: tool_tests-integration-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''"
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - dart --enable-asserts ./dev/bots/test.dart
-
- # TODO(ianh): Enable Web tests on macOS.
-
- - name: build_tests-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940
- script:
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-0-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-1-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-2-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-3-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-4-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: hostonly_devicelab_tests-5_last-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - dart --enable-asserts ./dev/bots/test.dart
-
- - name: add_to_app_tests-macos
- only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940
- skip: true # https://github.com/flutter/flutter/pull/42444
- script:
+ on_failure:
+ print_failure_time_script: date
+ - name: integration_tests-macos
+ only_if: $CIRRUS_BRANCH == 'master'
+ env:
+ SHARD: integration_tests
+ test_all_script:
- ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- dart --enable-asserts dev/bots/test.dart
-
+ - name: add2app-macos
+ skip: true # https://github.com/flutter/flutter/issues/39507
+ env:
+ SHARD: add2app_test
+ setup_xcpretty_script:
+ - sudo gem install xcpretty
+ test_all_script:
+ - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
+ - dart --enable-asserts dev/bots/test.dart
- name: customer_testing-macos
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
+ test_script:
- rm -rf bin/cache/pkg/tests
- git clone https://github.com/flutter/tests.git bin/cache/pkg/tests
- dart --enable-asserts dev/customer_testing/run_tests.dart --skip-on-fetch-failure --skip-template bin/cache/pkg/tests/registry/*.test
- - name: deploy_gallery-macos # linux- and macos- only
- depends_on:
- - analyze-linux
- - framework_tests-widgets-macos
- - framework_tests-libraries-macos
- - framework_tests-misc-macos
- - tool_tests-general-macos
- - tool_tests-commands-macos
- - tool_tests-integration-macos
- - build_tests-macos
- - hostonly_devicelab_tests-0-macos
- - hostonly_devicelab_tests-1-macos
- - hostonly_devicelab_tests-2-macos
- - hostonly_devicelab_tests-3-macos
- - hostonly_devicelab_tests-4-macos
- - hostonly_devicelab_tests-5_last-macos
- - firebase_test_lab_tests-linux
- environment:
- # Apple Fastlane password.
- FASTLANE_PASSWORD: ENCRYPTED[4b1f0b8d52874e9de965acd46c79743f3b81f3a513614179b9be7cf53dc8258753e257bdadb11a298ee455259df21865]
- # Private repo for publishing certificates.
- PUBLISHING_MATCH_CERTIFICATE_REPO: ENCRYPTED[3c0e78877d933fc80107aa6f3790fd1cf927250b852d6cb53202be696b4903ed8ca839b809626aaf18050bf7e436fab7]
- PUBLISHING_MATCH_REPO_TOKEN: ENCRYPTED[3d1230b744c6ed6c788a91bec741b769401dbcd426b18f9af8080bfeefdfc21913ca4047980c5b5b7ce823f12e7b6b19]
- # Apple Certificates Match Passphrase
- MATCH_PASSWORD: ENCRYPTED[db07f252234397090e3ec59152d9ec1831f5ecd0ef97d247b1dca757bbb9ef9b7c832a39bce2caf1949ccdf097e59a73]
- script:
- - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
- - ./dev/bots/deploy_gallery.sh
-
docker_builder:
# Only build a new docker image when we tag a release (for dev, beta, or release.)
only_if: $CIRRUS_TAG != ''
- environment:
+ env:
GCLOUD_CREDENTIALS: ENCRYPTED[f7c098d4dd7f5ee1bfee0bb7e944cce72efbe10e97ad6440ae72de4de6a1c24d23f421a2619c668e94377fb64b0bb3e6]
depends_on:
- - docs-linux
- - analyze-linux
- - framework_tests-widgets-linux
- - framework_tests-libraries-linux
- - framework_tests-misc-linux
- - tool_tests-general-linux
- - tool_tests-commands-linux
- - tool_tests-integration-linux
+ - docs
+ - analyze
+ - tests_widgets-linux
+ - tests_framework_other-linux
+ - tests_extras-linux
+ - tool_tests_general-linux
+ - tool_tests_commands-linux
+ - tool_tests_integration-linux
- build_tests-linux
- - hostonly_devicelab_tests-0-linux
- - hostonly_devicelab_tests-1-linux
- - hostonly_devicelab_tests-2-linux
- - hostonly_devicelab_tests-3-linux
- - hostonly_devicelab_tests-4-linux
- - hostonly_devicelab_tests-5_last-linux
- - firebase_test_lab_tests-linux
- script:
- - "$CIRRUS_WORKING_DIR/dev/ci/docker_linux/docker_build.sh"
- - "$CIRRUS_WORKING_DIR/dev/ci/docker_linux/docker_login.sh"
- - "$CIRRUS_WORKING_DIR/dev/ci/docker_linux/docker_push.sh"
+ - integration_tests-linux
+ - gradle_tests-linux-shard-1
+ - gradle_tests-linux-shard-2
+ - gradle_embedding_v2_tests-linux-shard-1
+ - gradle_embedding_v2_tests-linux-shard-2
+ - gradle_tests-windows-shard-1
+ - gradle_tests-windows-shard-2
+ - gradle_embedding_v2_tests-windows-shard-1
+ - gradle_embedding_v2_tests-windows-shard-2
+ - release_smoke_tests
+ build_script: "$CIRRUS_WORKING_DIR/dev/ci/docker_linux/docker_build.sh"
+ login_script: "$CIRRUS_WORKING_DIR/dev/ci/docker_linux/docker_login.sh"
+ push_script: "$CIRRUS_WORKING_DIR/dev/ci/docker_linux/docker_push.sh"
diff --git a/dev/README.md b/dev/README.md
index 3c287dd..afe8f26 100644
--- a/dev/README.md
+++ b/dev/README.md
@@ -2,6 +2,3 @@
during development of the framework. The tools in this directory
should not be necessary for developing Flutter applications, though of
course they may be interesting if you are curious.
-
-The tests in this directory are run in the `framework_tests_misc-*`
-shards.
diff --git a/dev/bots/accept_android_sdk_licenses.sh b/dev/bots/accept_android_sdk_licenses.sh
deleted file mode 100755
index a5b6abb..0000000
--- a/dev/bots/accept_android_sdk_licenses.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-set -e
-
-# This script is only meant to be run by the Cirrus CI system, not locally.
-# It must be run from the root of the Flutter repo.
-
-function error() {
- echo "$@" 1>&2
-}
-
-function accept_android_licenses() {
- yes "y" | flutter doctor --android-licenses > /dev/null 2>&1
-}
-
-echo "Flutter SDK directory is: $PWD"
-
-# Accept licenses.
-echo "Accepting Android licenses."
-accept_android_licenses || (error "Accepting Android licenses failed." && false)
diff --git a/dev/bots/cirrus_setup.sh b/dev/bots/cirrus_setup.sh
new file mode 100755
index 0000000..451bcbc
--- /dev/null
+++ b/dev/bots/cirrus_setup.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+set -e
+
+function error() {
+ echo "$@" 1>&2
+}
+
+# This script is only meant to be run by the Cirrus CI system, not locally.
+# It must be run from the root of the Flutter repo.
+
+function accept_android_licenses() {
+ yes "y" | flutter doctor --android-licenses > /dev/null 2>&1
+}
+
+echo "Flutter SDK directory is: $PWD"
+
+# Run flutter to download dependencies and precompile things, and to disable
+# analytics on the bots.
+echo "Downloading build dependencies and pre-compiling Flutter snapshot"
+./bin/flutter config --no-analytics
+
+# Run doctor, to print it to the log for debugging purposes.
+./bin/flutter doctor -v
+
+# Accept licenses.
+echo "Accepting Android licenses."
+accept_android_licenses || (error "Accepting Android licenses failed." && false)
+
+# Run pub get in all the repo packages.
+echo "Updating packages for Flutter."
+./bin/flutter update-packages
diff --git a/dev/bots/deploy_gallery.sh b/dev/bots/deploy_gallery.sh
index 86d34d9..f372fec 100755
--- a/dev/bots/deploy_gallery.sh
+++ b/dev/bots/deploy_gallery.sh
@@ -24,90 +24,88 @@
cd "$FLUTTER_ROOT"
-version="$(<version)"
-if [[ "$OS" == "linux" ]]; then
- echo "Building Flutter Gallery $version for Android..."
- # ANDROID_SDK_ROOT must be set in the env.
- (
- cd examples/flutter_gallery
- flutter build apk --release -t lib/main_publish.dart
- )
- echo "Android Flutter Gallery built"
- if [[ -z "$CIRRUS_PR" && "$CIRRUS_BRANCH" == "dev" && "$version" != *"pre"* ]]; then
- echo "Deploying Flutter Gallery $version to Play Store..."
- set +x # Don't echo back the below.
- if [ -n "$ANDROID_GALLERY_UPLOAD_KEY" ]; then
- echo "$ANDROID_GALLERY_UPLOAD_KEY" | base64 --decode > /root/.android/debug.keystore
- fi
- set -x
+if [[ "$SHARD" = "deploy_gallery" ]]; then
+ version="$(<version)"
+ if [[ "$OS" == "linux" ]]; then
+ echo "Building Flutter Gallery $version for Android..."
+
+ # ANDROID_SDK_ROOT must be set in the env.
(
- cd examples/flutter_gallery/android
- fastlane deploy_play_store
+ cd examples/flutter_gallery
+ flutter build apk --release -t lib/main_publish.dart
)
- else
- echo "(Not deploying; Flutter Gallery is only deployed to Play store for tagged dev branch commits.)"
- fi
-elif [[ "$OS" == "darwin" ]]; then
- echo "Building Flutter Gallery $version for iOS..."
- (
- cd examples/flutter_gallery
- flutter build ios --release --no-codesign -t lib/main_publish.dart
-
- # flutter build ios will run CocoaPods script. Check generated locations.
- if [[ ! -d "ios/Pods" ]]; then
- echo "Error: pod install failed to setup plugins"
- exit 1
- fi
-
- if [[ ! -d "ios/.symlinks/plugins" ]]; then
- echo "Error: pod install failed to setup plugin symlinks"
- exit 1
- fi
-
- if [[ -d "ios/.symlinks/flutter" ]]; then
- echo "Error: pod install created flutter symlink"
- exit 1
- fi
-
- if [[ ! -d "build/ios/iphoneos/Runner.app/Frameworks/App.framework/flutter_assets" ]]; then
- echo "Error: flutter_assets not assembled"
- exit 1
- fi
-
- if [[
- -d "build/ios/iphoneos/Runner.app/Frameworks/App.framework/flutter_assets/isolate_snapshot_data" ||
- -d "build/ios/iphoneos/Runner.app/Frameworks/App.framework/flutter_assets/kernel_blob.bin" ||
- -d "build/ios/iphoneos/Runner.app/Frameworks/App.framework/flutter_assets/vm_snapshot_data"
- ]]; then
- echo "Error: compiled debug version of app with --release flag"
- exit 1
- fi
- )
- echo "iOS Flutter Gallery built"
- if [[ -z "$CIRRUS_PR" ]]; then
- if [[ "$CIRRUS_BRANCH" == "dev" && "$version" != *"pre"* ]]; then
- echo "Archiving with distribution profile and deploying to TestFlight..."
+ echo "Android Flutter Gallery built"
+ if [[ -z "$CIRRUS_PR" && "$CIRRUS_BRANCH" == "dev" && "$version" != *"pre"* ]]; then
+ echo "Deploying Flutter Gallery $version to Play Store..."
+ set +x # Don't echo back the below.
+ if [ -n "$ANDROID_GALLERY_UPLOAD_KEY" ]; then
+ echo "$ANDROID_GALLERY_UPLOAD_KEY" | base64 --decode > /root/.android/debug.keystore
+ fi
+ set -x
(
- cd examples/flutter_gallery/ios
- export DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS="-t DAV"
- fastlane build_and_deploy_testflight upload:true
+ cd examples/flutter_gallery/android
+ fastlane deploy_play_store
)
else
- # On iOS the signing can break as well, so we verify this regularly (not just
- # on tagged dev branch commits). We can only do this post-merge, though, because
- # the secrets aren't available on PRs.
- echo "Testing archiving with distribution profile..."
- (
- cd examples/flutter_gallery/ios
- fastlane build_and_deploy_testflight
- )
- echo "(Not deploying; Flutter Gallery is only deployed to TestFlight for tagged dev branch commits.)"
+ echo "Not deployed: Flutter Gallery is only deployed to the Play Store on merged and tagged dev branch commits"
fi
- else
- echo "(Not archiving or deploying; Flutter Gallery archiving is only tested post-commit.)"
+ elif [[ "$OS" == "darwin" ]]; then
+ echo "Building Flutter Gallery $version for iOS..."
+ (
+ cd examples/flutter_gallery
+ flutter build ios --release --no-codesign -t lib/main_publish.dart
+
+ # flutter build ios will run CocoaPods script. Check generated locations.
+ if [[ ! -d "ios/Pods" ]]; then
+ echo "Error: pod install failed to setup plugins"
+ exit 1
+ fi
+
+ if [[ ! -d "ios/.symlinks/plugins" ]]; then
+ echo "Error: pod install failed to setup plugin symlinks"
+ exit 1
+ fi
+
+ if [[ -d "ios/.symlinks/flutter" ]]; then
+ echo "Error: pod install created flutter symlink"
+ exit 1
+ fi
+
+ if [[ ! -d "build/ios/iphoneos/Runner.app/Frameworks/App.framework/flutter_assets" ]]; then
+ echo "Error: flutter_assets not assembled"
+ exit 1
+ fi
+
+ if [[
+ -d "build/ios/iphoneos/Runner.app/Frameworks/App.framework/flutter_assets/isolate_snapshot_data" ||
+ -d "build/ios/iphoneos/Runner.app/Frameworks/App.framework/flutter_assets/kernel_blob.bin" ||
+ -d "build/ios/iphoneos/Runner.app/Frameworks/App.framework/flutter_assets/vm_snapshot_data"
+ ]]; then
+ echo "Error: compiled debug version of app with --release flag"
+ exit 1
+ fi
+ )
+ echo "iOS Flutter Gallery built"
+ if [[ -z "$CIRRUS_PR" ]]; then
+ if [[ "$CIRRUS_BRANCH" == "dev" && "$version" != *"pre"* ]]; then
+ echo "Archiving with distribution profile and deploying to TestFlight..."
+ (
+ cd examples/flutter_gallery/ios
+ export DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS="-t DAV"
+ fastlane build_and_deploy_testflight upload:true
+ )
+ else
+ echo "Archiving with distribution profile..."
+ (
+ cd examples/flutter_gallery/ios
+ fastlane build_and_deploy_testflight
+ )
+ echo "Archive is only deployed to TestFlight on tagged dev branch commits"
+ fi
+ else
+ echo "Not deployed: Flutter Gallery is only deployed to TestFlight on merged and tagged dev branch commits"
+ fi
fi
else
- echo "Unknown OS: $OS"
- echo "Aborted."
- exit 1
+ echo "Doing nothing: not on the 'deploy_gallery' SHARD."
fi
diff --git a/dev/bots/run_command.dart b/dev/bots/run_command.dart
index f240a5c..634a232 100644
--- a/dev/bots/run_command.dart
+++ b/dev/bots/run_command.dart
@@ -95,6 +95,7 @@
OutputMode outputMode = OutputMode.print,
CapturedOutput output,
bool skip = false,
+ bool expectFlaky = false,
bool Function(String) removeLine,
}) async {
assert((outputMode == OutputMode.capture) == (output != null),
@@ -144,6 +145,10 @@
output.stderr = _flattenToString(await savedStderr);
}
+ // If the test is flaky we don't care about the actual exit.
+ if (expectFlaky)
+ return;
+
if ((exitCode == 0) == expectNonZeroExit || (expectedExitCode != null && exitCode != expectedExitCode)) {
if (failureMessage != null) {
print(failureMessage);
diff --git a/dev/bots/test.dart b/dev/bots/test.dart
index fea54fb..9914dd2 100644
--- a/dev/bots/test.dart
+++ b/dev/bots/test.dart
@@ -4,11 +4,11 @@
import 'dart:async';
import 'dart:io';
-import 'dart:math' as math;
import 'package:googleapis/bigquery/v2.dart' as bq;
import 'package:googleapis_auth/auth_io.dart' as auth;
import 'package:http/http.dart' as http;
+import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'flutter_compact_formatter.dart';
@@ -30,54 +30,21 @@
final String pub = path.join(flutterRoot, 'bin', 'cache', 'dart-sdk', 'bin', Platform.isWindows ? 'pub.bat' : 'pub');
final String pubCache = path.join(flutterRoot, '.pub-cache');
final String toolRoot = path.join(flutterRoot, 'packages', 'flutter_tools');
-
-/// The arguments to pass to `flutter test` (typically the local engine
-/// configuration) -- prefilled with the arguments passed to test.dart.
final List<String> flutterTestArgs = <String>[];
final bool useFlutterTestFormatter = Platform.environment['FLUTTER_TEST_FORMATTER'] == 'true';
final bool canUseBuildRunner = Platform.environment['FLUTTER_TEST_NO_BUILD_RUNNER'] != 'true';
-/// The number of Cirrus jobs that run host-only devicelab tests in parallel.
-///
-/// WARNING: if you change this number, also change .cirrus.yml
-/// and make sure it runs _all_ shards.
-const int kDeviceLabShardCount = 6;
-
-/// The number of Cirrus jobs that run Web tests in parallel.
-///
-/// WARNING: if you change this number, also change .cirrus.yml
-/// and make sure it runs _all_ shards.
-///
-/// The last shard also runs the Web plugin tests.
-const int kWebShardCount = 6;
-
-/// Maximum number of Web tests to run in a single `flutter test`. We found that
-/// large batches can get flaky, possibly because we reuse a single instance of
-/// the browser, and after many tests the browser's state gets corrupted.
-const int kWebBatchSize = 20;
-
-/// Tests that we don't run on Web for various reasons.
-//
-// TODO(yjbanov): we're getting rid of these blacklists as part of https://github.com/flutter/flutter/projects/60
-const List<String> kWebTestDirectoryBlacklist = <String>[
- 'cupertino',
- 'examples',
- 'material',
-];
-const List<String> kWebTestFileBlacklist = <String>[
- 'test/widgets/heroes_test.dart',
- 'test/widgets/text_test.dart',
- 'test/widgets/selectable_text_test.dart',
- 'test/widgets/color_filter_test.dart',
- 'test/widgets/editable_text_cursor_test.dart',
- 'test/widgets/shadow_test.dart',
- 'test/widgets/raw_keyboard_listener_test.dart',
- 'test/widgets/editable_text_test.dart',
- 'test/widgets/widget_inspector_test.dart',
- 'test/widgets/draggable_test.dart',
- 'test/widgets/shortcuts_test.dart',
-];
+const Map<String, ShardRunner> _kShards = <String, ShardRunner>{
+ 'tests': _runTests,
+ 'web_tests': _runWebTests,
+ 'tool_tests': _runToolTests,
+ 'tool_coverage': _runToolCoverage,
+ 'build_tests': _runBuildTests,
+ 'coverage': _runCoverage,
+ 'integration_tests': _runIntegrationTests,
+ 'add2app_test': _runAdd2AppTest,
+};
/// When you call this, you can pass additional arguments to pass custom
/// arguments to flutter test. For example, you might want to call this
@@ -86,30 +53,31 @@
///
/// To run the tool_tests part, run it with SHARD=tool_tests
///
-/// Examples:
+/// For example:
/// SHARD=tool_tests bin/cache/dart-sdk/bin/dart dev/bots/test.dart
/// bin/cache/dart-sdk/bin/dart dev/bots/test.dart --local-engine=host_debug_unopt
Future<void> main(List<String> args) async {
flutterTestArgs.addAll(args);
- if (Platform.environment.containsKey(CIRRUS_TASK_NAME))
- print('Running task: ${Platform.environment[CIRRUS_TASK_NAME]}');
- print('═' * 80);
- await _runSmokeTests();
- print('═' * 80);
- await selectShard(const <String, ShardRunner>{
- 'add_to_app_tests': _runAddToAppTests,
- 'build_tests': _runBuildTests,
- 'framework_coverage': _runFrameworkCoverage,
- 'framework_tests': _runFrameworkTests,
- 'hostonly_devicelab_tests': _runHostOnlyDeviceLabTests,
- 'tool_coverage': _runToolCoverage,
- 'tool_tests': _runToolTests,
- 'web_tests': _runWebTests,
- });
+
+ final String shard = Platform.environment['SHARD'];
+ if (shard != null) {
+ if (!_kShards.containsKey(shard)) {
+ print('Invalid shard: $shard');
+ print('The available shards are: ${_kShards.keys.join(", ")}');
+ exit(1);
+ }
+ print('${bold}SHARD=$shard$reset');
+ await _kShards[shard]();
+ } else {
+ for (String currentShard in _kShards.keys) {
+ print('${bold}SHARD=$currentShard$reset');
+ await _kShards[currentShard]();
+ print('');
+ }
+ }
}
Future<void> _runSmokeTests() async {
- print('${green}Running smoketests...$reset');
// Verify that the tests actually return failure on failure and success on
// success.
final String automatedTests = path.join(flutterRoot, 'dev', 'automated_tests');
@@ -140,11 +108,10 @@
script: path.join('test_smoke_test', 'pending_timer_fail_test.dart'),
expectFailure: true,
printOutput: false,
- outputChecker: (CapturedOutput output) {
- return output.stdout.contains('failingPendingTimerTest')
- ? null
- : 'Failed to find the stack trace for the pending Timer.';
- }
+ outputChecker: (CapturedOutput output) =>
+ output.stdout.contains('failingPendingTimerTest')
+ ? null
+ : 'Failed to find the stack trace for the pending Timer.',
);
// We run the remaining smoketests in parallel, because they each take some
// time to run (e.g. compiling), so we don't want to run them in series,
@@ -186,11 +153,8 @@
);
// Verify that we correctly generated the version file.
- final String versionError = await verifyVersion(File(path.join(flutterRoot, 'version')));
- if (versionError != null) {
- print(redLine);
- print(versionError);
- print(redLine);
+ final bool validVersion = await verifyVersion(path.join(flutterRoot, 'version'));
+ if (!validVersion) {
exit(1);
}
}
@@ -215,7 +179,7 @@
final http.Client client = await auth.clientViaServiceAccount(accountCredentials, scopes);
return bq.BigqueryApi(client);
} catch (e) {
- print('${red}Failed to get BigQuery API client.$reset');
+ print('Failed to get BigQuery API client.');
print(e);
return null;
}
@@ -239,6 +203,7 @@
Future<void> _runToolTests() async {
final bq.BigqueryApi bigqueryApi = await _getBigqueryApi();
+ await _runSmokeTests();
const String kDotShard = '.shard';
const String kTest = 'test';
@@ -267,10 +232,11 @@
await selectSubshard(subshards);
}
-/// Verifies that AOT, APK, and IPA (if on macOS) builds the examples apps
-/// without crashing. It does not actually launch the apps. That happens later
-/// in the devicelab. This is just a smoke-test. In particular, this will verify
-/// we can build when there are spaces in the path name for the Flutter SDK and
+/// Verifies that AOT, APK, and IPA (if on macOS) builds the
+/// examples apps without crashing. It does not actually
+/// launch the apps. That happens later in the devicelab. This is
+/// just a smoke-test. In particular, this will verify we can build
+/// when there are spaces in the path name for the Flutter SDK and
/// target app.
Future<void> _runBuildTests() async {
final Stream<FileSystemEntity> exampleDirectories = Directory(path.join(flutterRoot, 'examples')).list();
@@ -279,11 +245,10 @@
continue;
}
final String examplePath = fileEntity.path;
+
await _flutterBuildAot(examplePath);
await _flutterBuildApk(examplePath);
- if (Platform.isMacOS) {
- await _flutterBuildIpa(examplePath);
- }
+ await _flutterBuildIpa(examplePath);
}
// Web compilation tests.
await _flutterBuildDart2js(path.join('dev', 'integration_tests', 'web'), path.join('lib', 'main.dart'));
@@ -291,44 +256,12 @@
await _flutterBuildDart2js(path.join('dev', 'integration_tests', 'web_compile_tests'),
path.join('lib', 'dart_io_import.dart'),
);
-}
-Future<void> _flutterBuildAot(String relativePathToApplication) async {
- print('${green}Testing AOT build$reset for $cyan$relativePathToApplication$reset...');
- await runCommand(flutter,
- <String>['build', 'aot', '-v'],
- workingDirectory: path.join(flutterRoot, relativePathToApplication),
- );
-}
-
-Future<void> _flutterBuildApk(String relativePathToApplication) async {
- print('${green}Testing APK --debug build$reset for $cyan$relativePathToApplication$reset...');
- await runCommand(flutter,
- <String>['build', 'apk', '--debug', '-v'],
- workingDirectory: path.join(flutterRoot, relativePathToApplication),
- );
-}
-
-Future<void> _flutterBuildIpa(String relativePathToApplication) async {
- assert(Platform.isMacOS);
- print('${green}Testing IPA build$reset for $cyan$relativePathToApplication$reset...');
- // Install Cocoapods. We don't have these checked in for the examples,
- // and build ios doesn't take care of it automatically.
- final File podfile = File(path.join(flutterRoot, relativePathToApplication, 'ios', 'Podfile'));
- if (podfile.existsSync()) {
- await runCommand('pod',
- <String>['install'],
- workingDirectory: podfile.parent.path,
- );
- }
- await runCommand(flutter,
- <String>['build', 'ios', '--no-codesign', '--debug', '-v'],
- workingDirectory: path.join(flutterRoot, relativePathToApplication),
- );
+ print('${bold}DONE: All build tests successful.$reset');
}
Future<void> _flutterBuildDart2js(String relativePathToApplication, String target, { bool expectNonZeroExit = false }) async {
- print('${green}Testing Dart2JS build$reset for $cyan$relativePathToApplication$reset...');
+ print('Running Dart2JS build tests...');
await runCommand(flutter,
<String>['build', 'web', '-v', '--target=$target'],
workingDirectory: path.join(flutterRoot, relativePathToApplication),
@@ -337,101 +270,211 @@
'FLUTTER_WEB': 'true',
},
);
+ print('Done.');
}
-Future<void> _runAddToAppTests() async {
- if (Platform.isMacOS) {
- print('${green}Running add-to-app iOS integration tests$reset...');
- final String addToAppDir = path.join(flutterRoot, 'dev', 'integration_tests', 'ios_add2app');
- await runCommand('./build_and_test.sh',
- <String>[],
- workingDirectory: addToAppDir,
+Future<void> _flutterBuildAot(String relativePathToApplication) async {
+ print('Running AOT build tests...');
+ await runCommand(flutter,
+ <String>['build', 'aot', '-v'],
+ workingDirectory: path.join(flutterRoot, relativePathToApplication),
+ expectNonZeroExit: false,
+ );
+ print('Done.');
+}
+
+Future<void> _flutterBuildApk(String relativePathToApplication) async {
+ if (
+ (Platform.environment['ANDROID_HOME']?.isEmpty ?? true) &&
+ (Platform.environment['ANDROID_SDK_ROOT']?.isEmpty ?? true)) {
+ return;
+ }
+ print('Running APK build tests...');
+ await runCommand(flutter,
+ <String>['build', 'apk', '--debug', '-v'],
+ workingDirectory: path.join(flutterRoot, relativePathToApplication),
+ expectNonZeroExit: false,
+ );
+ print('Done.');
+}
+
+Future<void> _flutterBuildIpa(String relativePathToApplication) async {
+ if (!Platform.isMacOS) {
+ return;
+ }
+ print('Running IPA build tests...');
+ // Install Cocoapods. We don't have these checked in for the examples,
+ // and build ios doesn't take care of it automatically.
+ final File podfile = File(path.join(flutterRoot, relativePathToApplication, 'ios', 'Podfile'));
+ if (podfile.existsSync()) {
+ await runCommand('pod',
+ <String>['install'],
+ workingDirectory: podfile.parent.path,
+ expectNonZeroExit: false,
);
}
+ await runCommand(flutter,
+ <String>['build', 'ios', '--no-codesign', '--debug', '-v'],
+ workingDirectory: path.join(flutterRoot, relativePathToApplication),
+ expectNonZeroExit: false,
+ );
+ print('Done.');
}
-Future<void> _runFrameworkTests() async {
+Future<void> _runAdd2AppTest() async {
+ if (!Platform.isMacOS) {
+ return;
+ }
+ print('Running Add2App iOS integration tests...');
+ final String add2AppDir = path.join(flutterRoot, 'dev', 'integration_tests', 'ios_add2app');
+ await runCommand('./build_and_test.sh',
+ <String>[],
+ workingDirectory: add2AppDir,
+ expectNonZeroExit: false,
+ );
+ print('Done.');
+}
+
+Future<void> _runTests() async {
final bq.BigqueryApi bigqueryApi = await _getBigqueryApi();
+ await _runSmokeTests();
+ final String subShard = Platform.environment['SUBSHARD'];
Future<void> runWidgets() async {
- print('${green}Running packages/flutter tests for$reset: ${cyan}test/widgets/$reset');
+ await _runFlutterTest(
+ path.join(flutterRoot, 'packages', 'flutter'),
+ tableData: bigqueryApi?.tabledata,
+ tests: <String>[
+ path.join('test', 'widgets') + path.separator,
+ ],
+ );
+ // Only packages/flutter/test/widgets/widget_inspector_test.dart really
+ // needs to be run with --track-widget-creation but it is nice to run
+ // all of the tests in package:flutter with the flag to ensure that
+ // the Dart kernel transformer triggered by the flag does not break anything.
await _runFlutterTest(
path.join(flutterRoot, 'packages', 'flutter'),
options: <String>['--track-widget-creation'],
tableData: bigqueryApi?.tabledata,
- tests: <String>[ path.join('test', 'widgets') + path.separator ],
+ tests: <String>[
+ path.join('test', 'widgets') + path.separator,
+ ],
);
- await _runFlutterTest(
- path.join(flutterRoot, 'packages', 'flutter'),
- options: <String>['--no-track-widget-creation'],
- tableData: bigqueryApi?.tabledata,
- tests: <String>[ path.join('test', 'widgets') + path.separator ],
- );
- // Try compiling code outside of the packages/flutter directory with and without --track-widget-creation
- await _runFlutterTest(path.join(flutterRoot, 'examples', 'flutter_gallery'), options: <String>['--track-widget-creation'], tableData: bigqueryApi?.tabledata);
- await _runFlutterTest(path.join(flutterRoot, 'examples', 'flutter_gallery'), options: <String>['--no-track-widget-creation'], tableData: bigqueryApi?.tabledata);
}
- Future<void> runLibraries() async {
+ Future<void> runFrameworkOthers() async {
final List<String> tests = Directory(path.join(flutterRoot, 'packages', 'flutter', 'test'))
.listSync(followLinks: false, recursive: false)
.whereType<Directory>()
.where((Directory dir) => dir.path.endsWith('widgets') == false)
- .map<String>((Directory dir) => path.join('test', path.basename(dir.path)) + path.separator)
+ .map((Directory dir) => path.join('test', path.basename(dir.path)) + path.separator)
.toList();
- print('${green}Running packages/flutter tests$reset for: $cyan${tests.join(", ")}$reset');
+
+ print('Running tests for: ${tests.join(';')}');
+
+ await _runFlutterTest(
+ path.join(flutterRoot, 'packages', 'flutter'),
+ tableData: bigqueryApi?.tabledata,
+ tests: tests,
+ );
+ // Only packages/flutter/test/widgets/widget_inspector_test.dart really
+ // needs to be run with --track-widget-creation but it is nice to run
+ // all of the tests in package:flutter with the flag to ensure that
+ // the Dart kernel transformer triggered by the flag does not break anything.
await _runFlutterTest(
path.join(flutterRoot, 'packages', 'flutter'),
options: <String>['--track-widget-creation'],
tableData: bigqueryApi?.tabledata,
tests: tests,
);
- await _runFlutterTest(
- path.join(flutterRoot, 'packages', 'flutter'),
- options: <String>['--no-track-widget-creation'],
- tableData: bigqueryApi?.tabledata,
- tests: tests,
- );
}
- Future<void> runMisc() async {
- print('${green}Running package tests$reset for directories other than packages/flutter');
+ Future<void> runExtras() async {
+ await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'), tableData: bigqueryApi?.tabledata);
+ await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'), tableData: bigqueryApi?.tabledata);
+ await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'), tableData: bigqueryApi?.tabledata);
+ await _runFlutterTest(path.join(flutterRoot, 'packages', 'fuchsia_remote_debug_protocol'), tableData: bigqueryApi?.tabledata);
await _pubRunTest(path.join(flutterRoot, 'dev', 'bots'), tableData: bigqueryApi?.tabledata);
await _pubRunTest(path.join(flutterRoot, 'dev', 'devicelab'), tableData: bigqueryApi?.tabledata);
await _pubRunTest(path.join(flutterRoot, 'dev', 'snippets'), tableData: bigqueryApi?.tabledata);
await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'android_semantics_testing'), tableData: bigqueryApi?.tabledata);
await _runFlutterTest(path.join(flutterRoot, 'dev', 'manual_tests'), tableData: bigqueryApi?.tabledata);
await _runFlutterTest(path.join(flutterRoot, 'dev', 'tools', 'vitool'), tableData: bigqueryApi?.tabledata);
- await _runFlutterTest(path.join(flutterRoot, 'examples', 'catalog'), tableData: bigqueryApi?.tabledata);
await _runFlutterTest(path.join(flutterRoot, 'examples', 'hello_world'), tableData: bigqueryApi?.tabledata);
await _runFlutterTest(path.join(flutterRoot, 'examples', 'layers'), tableData: bigqueryApi?.tabledata);
await _runFlutterTest(path.join(flutterRoot, 'examples', 'stocks'), tableData: bigqueryApi?.tabledata);
- await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'), tableData: bigqueryApi?.tabledata);
- await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'), tableData: bigqueryApi?.tabledata);
- await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'), tableData: bigqueryApi?.tabledata);
- await _runFlutterTest(path.join(flutterRoot, 'packages', 'fuchsia_remote_debug_protocol'), tableData: bigqueryApi?.tabledata);
- await _runFlutterTest(
- path.join(flutterRoot, 'dev', 'integration_tests', 'codegen'),
- tableData: bigqueryApi?.tabledata,
- environment: <String, String>{
- 'FLUTTER_EXPERIMENTAL_BUILD': 'true',
- },
- );
+ await _runFlutterTest(path.join(flutterRoot, 'examples', 'flutter_gallery'), tableData: bigqueryApi?.tabledata);
+ // Regression test to ensure that code outside of package:flutter can run
+ // with --track-widget-creation.
+ await _runFlutterTest(path.join(flutterRoot, 'examples', 'flutter_gallery'), options: <String>['--track-widget-creation'], tableData: bigqueryApi?.tabledata);
+ await _runFlutterTest(path.join(flutterRoot, 'examples', 'catalog'), tableData: bigqueryApi?.tabledata);
+ // Smoke test for code generation.
+ await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'codegen'), tableData: bigqueryApi?.tabledata, environment: <String, String>{
+ 'FLUTTER_EXPERIMENTAL_BUILD': 'true',
+ });
+ }
+ switch (subShard) {
+ case 'widgets':
+ await runWidgets();
+ break;
+ case 'framework_other':
+ await runFrameworkOthers();
+ break;
+ case 'extras':
+ runExtras();
+ break;
+ default:
+ print('Unknown sub-shard $subShard, running all tests!');
+ await runWidgets();
+ await runFrameworkOthers();
+ await runExtras();
+
}
- await selectSubshard(<String, ShardRunner>{
- 'widgets': runWidgets,
- 'libraries': runLibraries,
- 'misc': runMisc,
- });
+ print('${bold}DONE: All tests successful.$reset');
}
-Future<void> _runFrameworkCoverage() async {
+// TODO(yjbanov): we're getting rid of these blacklists as part of https://github.com/flutter/flutter/projects/60
+const List<String> kWebTestDirectoryBlacklist = <String>[
+ 'test/cupertino',
+ 'test/examples',
+ 'test/material',
+];
+const List<String> kWebTestFileBlacklist = <String>[
+ 'test/widgets/heroes_test.dart',
+ 'test/widgets/text_test.dart',
+ 'test/widgets/selectable_text_test.dart',
+ 'test/widgets/color_filter_test.dart',
+ 'test/widgets/editable_text_cursor_test.dart',
+ 'test/widgets/shadow_test.dart',
+ 'test/widgets/raw_keyboard_listener_test.dart',
+ 'test/widgets/editable_text_test.dart',
+ 'test/widgets/widget_inspector_test.dart',
+ 'test/widgets/draggable_test.dart',
+ 'test/widgets/shortcuts_test.dart',
+];
+
+Future<void> _runWebTests() async {
+ final Directory flutterPackageDir = Directory(path.join(flutterRoot, 'packages', 'flutter'));
+ final Directory testDir = Directory(path.join(flutterPackageDir.path, 'test'));
+
+ final List<String> directories = testDir
+ .listSync()
+ .whereType<Directory>()
+ .map<String>((Directory dir) => path.relative(dir.path, from: flutterPackageDir.path))
+ .where((String relativePath) => !kWebTestDirectoryBlacklist.contains(relativePath))
+ .toList();
+
+ await _runFlutterWebTest(flutterPackageDir.path, tests: directories);
+ await _runFlutterWebTest(path.join(flutterRoot, 'packages', 'flutter_web_plugins'), tests: <String>['test']);
+}
+
+Future<void> _runCoverage() async {
final File coverageFile = File(path.join(flutterRoot, 'packages', 'flutter', 'coverage', 'lcov.info'));
if (!coverageFile.existsSync()) {
print('${red}Coverage file not found.$reset');
- print('Expected to find: $cyan${coverageFile.absolute}$reset');
- print('This file is normally obtained by running `${green}flutter update-packages$reset`.');
+ print('Expected to find: ${coverageFile.absolute}');
+ print('This file is normally obtained by running `flutter update-packages`.');
exit(1);
}
coverageFile.deleteSync();
@@ -440,98 +483,11 @@
);
if (!coverageFile.existsSync()) {
print('${red}Coverage file not found.$reset');
- print('Expected to find: $cyan${coverageFile.absolute}$reset');
- print('This file should have been generated by the `${green}flutter test --coverage$reset` script, but was not.');
+ print('Expected to find: ${coverageFile.absolute}');
+ print('This file should have been generated by the `flutter test --coverage` script, but was not.');
exit(1);
}
-}
-
-Future<void> _runWebTests() async {
- final Map<String, ShardRunner> subshards = <String, ShardRunner>{};
-
- final Directory flutterPackageDirectory = Directory(path.join(flutterRoot, 'packages', 'flutter'));
- final Directory flutterPackageTestDirectory = Directory(path.join(flutterPackageDirectory.path, 'test'));
-
- final List<String> allTests = flutterPackageTestDirectory
- .listSync()
- .whereType<Directory>()
- .where((Directory directory) => !kWebTestDirectoryBlacklist.contains(path.basename(directory.path)))
- .expand((Directory directory) => directory
- .listSync(recursive: true)
- .where((FileSystemEntity entity) => entity.path.endsWith('_test.dart'))
- )
- .whereType<File>()
- .map<String>((File file) => path.relative(file.path, from: flutterPackageDirectory.path))
- .where((String filePath) => !kWebTestFileBlacklist.contains(filePath))
- .toList()
- // Finally we shuffle the list because we want the average cost per file to be uniformly
- // distributed. If the list is not sorted then different shards and batches may have
- // very different characteristics.
- // We use a constant seed for repeatability.
- ..shuffle(math.Random(0));
-
- assert(kWebShardCount >= 1);
- final int testsPerShard = (allTests.length / kWebShardCount).ceil();
- assert(testsPerShard * kWebShardCount >= allTests.length);
-
- // This for loop computes all but the last shard.
- for (int index = 0; index < kWebShardCount - 1; index += 1) {
- subshards['$index'] = () => _runFlutterWebTest(
- flutterPackageDirectory.path,
- allTests.sublist(
- index * testsPerShard,
- (index + 1) * testsPerShard,
- ),
- );
- }
-
- // The last shard also runs the flutter_web_plugins tests.
- //
- // We make sure the last shard ends in _last so it's easier to catch mismatches
- // between `.cirrus.yml` and `test.dart`.
- subshards['${kWebShardCount - 1}_last'] = () async {
- await _runFlutterWebTest(
- flutterPackageDirectory.path,
- allTests.sublist(
- (kWebShardCount - 1) * testsPerShard,
- allTests.length,
- ),
- );
- await _runFlutterWebTest(
- path.join(flutterRoot, 'packages', 'flutter_web_plugins'),
- <String>['test'],
- );
- };
-
- await selectSubshard(subshards);
-}
-
-Future<void> _runFlutterWebTest(String workingDirectory, List<String> tests) async {
- final List<String> batch = <String>[];
- for (int i = 0; i < tests.length; i += 1) {
- final String testFilePath = tests[i];
- batch.add(testFilePath);
- if (batch.length == kWebBatchSize || i == tests.length - 1) {
- await runCommand(
- flutter,
- <String>[
- 'test',
- if (ciProvider == CiProviders.cirrus)
- '--concurrency=1', // do not parallelize on Cirrus, to reduce flakiness
- '-v',
- '--platform=chrome',
- ...?flutterTestArgs,
- ...batch,
- ],
- workingDirectory: workingDirectory,
- environment: <String, String>{
- 'FLUTTER_WEB': 'true',
- 'FLUTTER_LOW_RESOURCE_MODE': 'true',
- },
- );
- batch.clear();
- }
- }
+ print('${bold}DONE: Coverage collection successful.$reset');
}
Future<void> _pubRunTest(String workingDirectory, {
@@ -540,33 +496,14 @@
bool useBuildRunner = false,
bq.TabledataResourceApi tableData,
}) async {
- final List<String> args = <String>['run'];
+ final List<String> args = <String>['run', '--verbose'];
if (useBuildRunner) {
- final String posixTestPath = path.posix.joinAll(path.split(testPath));
- args.addAll(<String>[
- 'build_runner',
- 'test',
- '--build-filter=$posixTestPath/*.dill',
- '--build-filter=$posixTestPath/**/*.dill',
- '--',
- ]);
+ args.addAll(<String>['build_runner', 'test', '--']);
} else {
args.add('test');
}
args.add(useFlutterTestFormatter ? '-rjson' : '-rcompact');
- int cpus;
- final String cpuVariable = Platform.environment['CPU']; // CPU is set in cirrus.yml
- if (cpuVariable != null) {
- cpus = int.tryParse(cpuVariable, radix: 10);
- if (cpus == null) {
- print('${red}The CPU environment variable, if set, must be set to the integer number of available cores.$reset');
- print('Actual value: "$cpuVariable"');
- exit(1);
- }
- } else {
- cpus = 2; // Don't default to 1, otherwise we won't catch race conditions.
- }
- args.add('-j$cpus');
+ args.add('-j1'); // TODO(ianh): Scale based on CPUs.
if (!hasColor)
args.add('--no-color');
if (testPath != null)
@@ -610,6 +547,238 @@
}
}
+void deleteFile(String path) {
+ // There's a race condition here but in theory we're not racing anyone
+ // while this script runs, so should be ok.
+ final File file = File(path);
+ if (file.existsSync())
+ file.deleteSync();
+}
+
+enum CiProviders {
+ cirrus,
+ luci,
+}
+
+CiProviders _getCiProvider() {
+ if (Platform.environment['CIRRUS_CI'] == 'true') {
+ return CiProviders.cirrus;
+ }
+ if (Platform.environment['LUCI_CONTEXT'] != null) {
+ return CiProviders.luci;
+ }
+ return null;
+}
+
+String _getCiProviderName() {
+ switch(_getCiProvider()) {
+ case CiProviders.cirrus:
+ return 'cirrusci';
+ case CiProviders.luci:
+ return 'luci';
+ }
+ return 'unknown';
+}
+
+int _getPrNumber() {
+ switch(_getCiProvider()) {
+ case CiProviders.cirrus:
+ return Platform.environment['CIRRUS_PR'] == null
+ ? -1
+ : int.tryParse(Platform.environment['CIRRUS_PR']);
+ case CiProviders.luci:
+ return -1; // LUCI doesn't know about this.
+ }
+ return -1;
+}
+
+Future<String> _getAuthors() async {
+ final String exe = Platform.isWindows ? '.exe' : '';
+ final String author = await runAndGetStdout(
+ 'git$exe', <String>['-c', 'log.showSignature=false', 'log', _getGitHash(), '--pretty="%an <%ae>"'],
+ workingDirectory: flutterRoot,
+ ).first;
+ return author;
+}
+
+String _getCiUrl() {
+ switch(_getCiProvider()) {
+ case CiProviders.cirrus:
+ return 'https://cirrus-ci.com/task/${Platform.environment['CIRRUS_TASK_ID']}';
+ case CiProviders.luci:
+ return 'https://ci.chromium.org/p/flutter/g/framework/console'; // TODO(dnfield): can we get a direct link to the actual build?
+ }
+ return '';
+}
+
+String _getGitHash() {
+ switch(_getCiProvider()) {
+ case CiProviders.cirrus:
+ return Platform.environment['CIRRUS_CHANGE_IN_REPO'];
+ case CiProviders.luci:
+ return 'HEAD'; // TODO(dnfield): Set this in the env for LUCI.
+ }
+ return '';
+}
+
+Future<void> _processTestOutput(
+ FlutterCompactFormatter formatter,
+ Stream<String> testOutput,
+ bq.TabledataResourceApi tableData,
+) async {
+ final Timer heartbeat = Timer.periodic(const Duration(seconds: 30), (Timer timer) {
+ print('Processing...');
+ });
+
+ await testOutput.forEach(formatter.processRawOutput);
+ heartbeat.cancel();
+ formatter.finish();
+ if (tableData == null || formatter.tests.isEmpty) {
+ return;
+ }
+ final bq.TableDataInsertAllRequest request = bq.TableDataInsertAllRequest();
+ final String authors = await _getAuthors();
+ request.rows = List<bq.TableDataInsertAllRequestRows>.from(
+ formatter.tests.map<bq.TableDataInsertAllRequestRows>((TestResult result) =>
+ bq.TableDataInsertAllRequestRows.fromJson(<String, dynamic> {
+ 'json': <String, dynamic>{
+ 'source': <String, dynamic>{
+ 'provider': _getCiProviderName(),
+ 'url': _getCiUrl(),
+ 'platform': <String, dynamic>{
+ 'os': Platform.operatingSystem,
+ 'version': Platform.operatingSystemVersion,
+ },
+ },
+ 'test': <String, dynamic>{
+ 'name': result.name,
+ 'result': result.status.toString(),
+ 'file': result.path,
+ 'line': result.line,
+ 'column': result.column,
+ 'time': result.totalTime,
+ },
+ 'git': <String, dynamic>{
+ 'author': authors,
+ 'pull_request': _getPrNumber(),
+ 'commit': _getGitHash(),
+ 'organization': 'flutter',
+ 'repository': 'flutter',
+ },
+ 'error': result.status != TestStatus.failed ? null : <String, dynamic>{
+ 'message': result.errorMessage,
+ 'stack_trace': result.stackTrace,
+ },
+ 'information': result.messages,
+ },
+ }),
+ ),
+ growable: false,
+ );
+ final bq.TableDataInsertAllResponse response = await tableData.insertAll(request, 'flutter-infra', 'tests', 'ci');
+ if (response.insertErrors != null && response.insertErrors.isNotEmpty) {
+ print('${red}BigQuery insert errors:');
+ print(response.toJson());
+ print(reset);
+ }
+}
+
+class EvalResult {
+ EvalResult({
+ this.stdout,
+ this.stderr,
+ this.exitCode = 0,
+ });
+
+ final String stdout;
+ final String stderr;
+ final int exitCode;
+}
+
+/// The number of Cirrus jobs that run web tests in parallel.
+///
+/// WARNING: if you change this number, also change .cirrus.yml
+/// and make sure it runs _all_ shards.
+const int _kWebShardCount = 6;
+
+Future<void> _runFlutterWebTest(String workingDirectory, {
+ List<String> tests,
+}) async {
+ List<String> allTests = <String>[];
+ for (String testDirPath in tests) {
+ final Directory testDir = Directory(path.join(workingDirectory, testDirPath));
+ allTests.addAll(
+ testDir.listSync(recursive: true)
+ .whereType<File>()
+ .where((File file) => file.path.endsWith('_test.dart'))
+ .map<String>((File file) => path.relative(file.path, from: workingDirectory))
+ .where((String filePath) => !kWebTestFileBlacklist.contains(filePath)),
+ );
+ }
+
+ // If a shard is specified only run tests in that shard.
+ final int webShard = int.tryParse(Platform.environment['WEB_SHARD'] ?? 'n/a');
+ if (webShard != null) {
+ if (webShard >= _kWebShardCount) {
+ throw 'WEB_SHARD must be <= _kWebShardCount, but was $webShard';
+ }
+ final List<String> shard = <String>[];
+ for (int i = webShard; i < allTests.length; i += _kWebShardCount) {
+ shard.add(allTests[i]);
+ }
+ allTests = shard;
+ }
+
+ print(allTests.join('\n'));
+ print('${allTests.length} tests total');
+
+ // Maximum number of tests to run in a single `flutter test`. We found that
+ // large batches can get flaky, possibly because we reuse a single instance
+ // of the browser, and after many tests the browser's state gets corrupted.
+ const int kBatchSize = 20;
+ List<String> batch = <String>[];
+ for (int i = 0; i < allTests.length; i += 1) {
+ final String testFilePath = allTests[i];
+ batch.add(testFilePath);
+ if (batch.length == kBatchSize || i == allTests.length - 1) {
+ await _runFlutterWebTestBatch(workingDirectory, batch: batch);
+ batch = <String>[];
+ }
+ }
+}
+
+Future<void> _runFlutterWebTestBatch(String workingDirectory, {
+ List<String> batch,
+}) async {
+ final List<String> args = <String>[
+ 'test',
+ if (_getCiProvider() == CiProviders.cirrus)
+ '--concurrency=1', // do not parallelize on Cirrus to reduce flakiness
+ '-v',
+ '--platform=chrome',
+ ...?flutterTestArgs,
+ ...batch,
+ ];
+
+ // TODO(jonahwilliams): fix relative path issues to make this unecessary.
+ final Directory oldCurrent = Directory.current;
+ Directory.current = Directory(path.join(flutterRoot, 'packages', 'flutter'));
+ try {
+ await runCommand(
+ flutter,
+ args,
+ workingDirectory: workingDirectory,
+ expectFlaky: false,
+ environment: <String, String>{
+ 'FLUTTER_WEB': 'true',
+ 'FLUTTER_LOW_RESOURCE_MODE': 'true',
+ },
+ );
+ } finally {
+ Directory.current = oldCurrent;
+ }
+}
+
Future<void> _runFlutterTest(String workingDirectory, {
String script,
bool expectFailure = false,
@@ -621,7 +790,8 @@
Map<String, String> environment,
List<String> tests = const <String>[],
}) async {
- assert(!printOutput || outputChecker == null, 'Output either can be printed or checked but not both');
+ assert(!printOutput || outputChecker == null,
+ 'Output either can be printed or checked but not both');
final List<String> args = <String>[
'test',
@@ -630,15 +800,16 @@
];
final bool shouldProcessOutput = useFlutterTestFormatter && !expectFailure && !options.contains('--coverage');
- if (shouldProcessOutput)
+ if (shouldProcessOutput) {
args.add('--machine');
+ }
if (script != null) {
final String fullScriptPath = path.join(workingDirectory, script);
if (!FileSystemEntity.isFileSync(fullScriptPath)) {
- print('${red}Could not find test$reset: $green$fullScriptPath$reset');
- print('Working directory: $cyan$workingDirectory$reset');
- print('Script: $green$script$reset');
+ print('Could not find test: $fullScriptPath');
+ print('Working directory: $workingDirectory');
+ print('Script: $script');
if (!printOutput)
print('This is one of the tests that does not normally print output.');
if (skip)
@@ -705,290 +876,110 @@
}
}
-Map<String, String> _initGradleEnvironment() {
- final String androidSdkRoot = (Platform.environment['ANDROID_HOME']?.isEmpty ?? true)
- ? Platform.environment['ANDROID_SDK_ROOT']
- : Platform.environment['ANDROID_HOME'];
- if (androidSdkRoot == null || androidSdkRoot.isEmpty) {
- print('${red}Could not find Android SDK; set ANDROID_SDK_ROOT (or ANDROID_HOME).$reset');
- exit(1);
+// the optional `file` argument is an override for testing
+@visibleForTesting
+Future<bool> verifyVersion(String filename, [File file]) async {
+ final RegExp pattern = RegExp(r'^\d+\.\d+\.\d+(\+hotfix\.\d+)?(-pre\.\d+)?$');
+ file ??= File(filename);
+ final String version = await file.readAsString();
+ if (!file.existsSync()) {
+ print('$redLine');
+ print('The version logic failed to create the Flutter version file.');
+ print('$redLine');
+ return false;
}
- return <String, String>{
- 'ANDROID_HOME': androidSdkRoot,
- 'ANDROID_SDK_ROOT': androidSdkRoot,
- };
+ if (version == '0.0.0-unknown') {
+ print('$redLine');
+ print('The version logic failed to determine the Flutter version.');
+ print('$redLine');
+ return false;
+ }
+ if (!version.contains(pattern)) {
+ print('$redLine');
+ print('The version logic generated an invalid version string: "$version".');
+ print('$redLine');
+ return false;
+ }
+ return true;
}
-final Map<String, String> gradleEnvironment = _initGradleEnvironment();
+Future<void> _runIntegrationTests() async {
+ final String subShard = Platform.environment['SUBSHARD'];
-Future<void> _runHostOnlyDeviceLabTests() async {
- if (Platform.isWindows) {
- // TODO(ianh): remove when https://github.com/flutter/flutter/issues/36311 fixed by https://github.com/flutter/flutter/pull/42709
- return;
+ switch (subShard) {
+ case 'gradle1':
+ case 'gradle2':
+ // This runs some gradle integration tests if the subshard is Android.
+ await _androidGradleTests(subShard);
+ break;
+ default:
+ await _runDevicelabTest('dartdocs');
+
+ if (Platform.isLinux) {
+ await _runDevicelabTest('flutter_create_offline_test_linux');
+ } else if (Platform.isWindows) {
+ await _runDevicelabTest('flutter_create_offline_test_windows');
+ } else if (Platform.isMacOS) {
+ await _runDevicelabTest('flutter_create_offline_test_mac');
+ await _runDevicelabTest('plugin_lint_mac');
+// TODO(jmagman): Re-enable once flakiness is resolved.
+// await _runDevicelabTest('module_test_ios');
+ }
}
-
- // Please don't add more tests here. We should not be using the devicelab
- // logic to run tests outside devicelab, that's just confusing.
- // Instead, create tests that are not devicelab tests, and run those.
-
- // TODO(ianh): Move the tests that are not running on devicelab any more out
- // of the device lab directory.
-
- // List the tests to run.
- // We split these into subshards. The tests are randomly distributed into
- // those subshards so as to get a uniform distribution of costs, but the
- // seed is fixed so that issues are reproducible.
- final List<ShardRunner> tests = <ShardRunner>[
- // Keep this in alphabetical order.
- () => _runDevicelabTest('build_aar_module_test', environment: gradleEnvironment, testEmbeddingV2: true),
- () => _runDevicelabTest('build_aar_module_test', environment: gradleEnvironment, testEmbeddingV2: false),
- if (Platform.isMacOS) () => _runDevicelabTest('flutter_create_offline_test_mac'),
- if (Platform.isLinux) () => _runDevicelabTest('flutter_create_offline_test_linux'),
- if (Platform.isWindows) () => _runDevicelabTest('flutter_create_offline_test_windows'),
- // TODO(ianh): Fails on macOS looking for "dexdump", https://github.com/flutter/flutter/issues/42494
- if (!Platform.isMacOS) () => _runDevicelabTest('gradle_jetifier_test', environment: gradleEnvironment, testEmbeddingV2: false),
- if (!Platform.isMacOS) () => _runDevicelabTest('gradle_jetifier_test', environment: gradleEnvironment, testEmbeddingV2: true),
- () => _runDevicelabTest('gradle_non_android_plugin_test', environment: gradleEnvironment, testEmbeddingV2: false),
- () => _runDevicelabTest('gradle_non_android_plugin_test', environment: gradleEnvironment, testEmbeddingV2: true),
- () => _runDevicelabTest('gradle_plugin_bundle_test', environment: gradleEnvironment, testEmbeddingV2: false),
- () => _runDevicelabTest('gradle_plugin_bundle_test', environment: gradleEnvironment, testEmbeddingV2: true),
- () => _runDevicelabTest('gradle_plugin_fat_apk_test', environment: gradleEnvironment, testEmbeddingV2: false),
- () => _runDevicelabTest('gradle_plugin_fat_apk_test', environment: gradleEnvironment, testEmbeddingV2: true),
- () => _runDevicelabTest('gradle_plugin_light_apk_test', environment: gradleEnvironment, testEmbeddingV2: false),
- () => _runDevicelabTest('gradle_plugin_light_apk_test', environment: gradleEnvironment, testEmbeddingV2: true),
- () => _runDevicelabTest('gradle_r8_test', environment: gradleEnvironment, testEmbeddingV2: false),
- () => _runDevicelabTest('gradle_r8_test', environment: gradleEnvironment, testEmbeddingV2: true),
- () => _runDevicelabTest('module_host_with_custom_build_test', environment: gradleEnvironment, testEmbeddingV2: false),
- () => _runDevicelabTest('module_host_with_custom_build_test', environment: gradleEnvironment, testEmbeddingV2: true),
- () => _runDevicelabTest('module_test', environment: gradleEnvironment, testEmbeddingV2: false),
- () => _runDevicelabTest('module_test', environment: gradleEnvironment, testEmbeddingV2: true),
- // TODO(jmagman): Re-enable once flakiness is resolved, https://github.com/flutter/flutter/issues/37525
- // if (Platform.isMacOS) () => _runDevicelabTest('module_test_ios'),
- if (Platform.isMacOS) () => _runDevicelabTest('plugin_lint_mac'),
- () => _runDevicelabTest('plugin_test', environment: gradleEnvironment, testEmbeddingV2: false),
- () => _runDevicelabTest('plugin_test', environment: gradleEnvironment, testEmbeddingV2: true),
- ]..shuffle(math.Random(0));
-
- final int testsPerShard = tests.length ~/ kDeviceLabShardCount;
- final Map<String, ShardRunner> subshards = <String, ShardRunner>{};
-
- for (int subshard = 0; subshard < kDeviceLabShardCount; subshard += 1) {
- String last = '';
- List<ShardRunner> sublist;
- if (subshard < kDeviceLabShardCount - 1) {
- sublist = tests.sublist(subshard * testsPerShard, (subshard + 1) * testsPerShard);
- } else {
- sublist = tests.sublist(subshard * testsPerShard, tests.length);
- // We make sure the last shard ends in _last so it's easier to catch mismatches
- // between `.cirrus.yml` and `test.dart`.
- last = '_last';
- }
- subshards['$subshard$last'] = () async {
- for (ShardRunner test in sublist)
- await test();
- };
- }
-
- await selectSubshard(subshards);
}
-Future<void> _runDevicelabTest(String testName, {
- Map<String, String> environment,
- bool testEmbeddingV2 = false,
-}) async {
+Future<void> _runDevicelabTest(String testName, {Map<String, String> env}) async {
await runCommand(
dart,
<String>['bin/run.dart', '-t', testName],
workingDirectory: path.join(flutterRoot, 'dev', 'devicelab'),
- environment: <String, String>{
- ...?environment,
- if (testEmbeddingV2)
- 'ENABLE_ANDROID_EMBEDDING_V2': 'true',
- },
+ environment: env,
);
}
-void deleteFile(String path) {
- // This is technically a race condition but nobody else should be running
- // while this script runs, so we should be ok. (Sadly recursive:true does not
- // obviate the need for existsSync, at least on Windows.)
- final File file = File(path);
- if (file.existsSync())
- file.deleteSync();
+String get androidSdkRoot {
+ final String androidSdkRoot = (Platform.environment['ANDROID_HOME']?.isEmpty ?? true)
+ ? Platform.environment['ANDROID_SDK_ROOT']
+ : Platform.environment['ANDROID_HOME'];
+ if (androidSdkRoot == null || androidSdkRoot.isEmpty) {
+ return null;
+ }
+ return androidSdkRoot;
}
-enum CiProviders {
- cirrus,
- luci,
-}
-
-Future<void> _processTestOutput(
- FlutterCompactFormatter formatter,
- Stream<String> testOutput,
- bq.TabledataResourceApi tableData,
-) async {
- final Timer heartbeat = Timer.periodic(const Duration(seconds: 30), (Timer timer) {
- print('Processing...');
- });
-
- await testOutput.forEach(formatter.processRawOutput);
- heartbeat.cancel();
- formatter.finish();
- if (tableData == null || formatter.tests.isEmpty) {
+Future<void> _androidGradleTests(String subShard) async {
+ // TODO(dnfield): gradlew is crashing on the cirrus image and it's not clear why.
+ if (androidSdkRoot == null || Platform.isWindows) {
+ print('No Android SDK detected or on Windows, skipping Android gradle test.');
return;
}
- final bq.TableDataInsertAllRequest request = bq.TableDataInsertAllRequest();
- final String authors = await _getAuthors();
- request.rows = List<bq.TableDataInsertAllRequestRows>.from(
- formatter.tests.map<bq.TableDataInsertAllRequestRows>((TestResult result) =>
- bq.TableDataInsertAllRequestRows.fromJson(<String, dynamic> {
- 'json': <String, dynamic>{
- 'source': <String, dynamic>{
- 'provider': ciProviderName,
- 'url': ciUrl,
- 'platform': <String, dynamic>{
- 'os': Platform.operatingSystem,
- 'version': Platform.operatingSystemVersion,
- },
- },
- 'test': <String, dynamic>{
- 'name': result.name,
- 'result': result.status.toString(),
- 'file': result.path,
- 'line': result.line,
- 'column': result.column,
- 'time': result.totalTime,
- },
- 'git': <String, dynamic>{
- 'author': authors,
- 'pull_request': prNumber,
- 'commit': gitHash,
- 'organization': 'flutter',
- 'repository': 'flutter',
- },
- 'error': result.status != TestStatus.failed ? null : <String, dynamic>{
- 'message': result.errorMessage,
- 'stack_trace': result.stackTrace,
- },
- 'information': result.messages,
- },
- }),
- ),
- growable: false,
- );
- final bq.TableDataInsertAllResponse response = await tableData.insertAll(request, 'flutter-infra', 'tests', 'ci');
- if (response.insertErrors != null && response.insertErrors.isNotEmpty) {
- print('${red}BigQuery insert errors:');
- print(response.toJson());
- print(reset);
+ final Map<String, String> defaultEnv = <String, String>{
+ 'ANDROID_HOME': androidSdkRoot,
+ 'ANDROID_SDK_ROOT': androidSdkRoot,
+ 'ENABLE_ANDROID_EMBEDDING_V2': Platform.environment['ENABLE_ANDROID_EMBEDDING_V2'] ?? '',
+ };
+ if (subShard == 'gradle1') {
+ await _runDevicelabTest('gradle_plugin_light_apk_test', env: defaultEnv);
+ await _runDevicelabTest('gradle_plugin_fat_apk_test', env: defaultEnv);
+ await _runDevicelabTest('gradle_r8_test', env: defaultEnv);
+ await _runDevicelabTest('gradle_non_android_plugin_test', env: defaultEnv);
+ await _runDevicelabTest('gradle_jetifier_test', env: defaultEnv);
+ }
+ if (subShard == 'gradle2') {
+ await _runDevicelabTest('gradle_plugin_bundle_test', env: defaultEnv);
+ await _runDevicelabTest('module_test', env: defaultEnv);
+ await _runDevicelabTest('module_host_with_custom_build_test', env: defaultEnv);
+ await _runDevicelabTest('build_aar_module_test', env: defaultEnv);
+ await _runDevicelabTest('plugin_test', env: defaultEnv);
}
}
-CiProviders get ciProvider {
- if (Platform.environment['CIRRUS_CI'] == 'true') {
- return CiProviders.cirrus;
- }
- if (Platform.environment['LUCI_CONTEXT'] != null) {
- return CiProviders.luci;
- }
- return null;
-}
+Future<void> selectShard(Map<String, ShardRunner> shards) => _runFromList(shards, 'SHARD', 'shard');
+Future<void> selectSubshard(Map<String, ShardRunner> subshards) => _runFromList(subshards, 'SUBSHARD', 'subshard');
-String get ciProviderName {
- switch (ciProvider) {
- case CiProviders.cirrus:
- return 'cirrusci';
- case CiProviders.luci:
- return 'luci';
- }
- return 'unknown';
-}
-
-int get prNumber {
- switch (ciProvider) {
- case CiProviders.cirrus:
- return Platform.environment['CIRRUS_PR'] == null
- ? -1
- : int.tryParse(Platform.environment['CIRRUS_PR']);
- case CiProviders.luci:
- return -1; // LUCI doesn't know about this.
- }
- return -1;
-}
-
-Future<String> _getAuthors() async {
- final String exe = Platform.isWindows ? '.exe' : '';
- final String author = await runAndGetStdout(
- 'git$exe', <String>['-c', 'log.showSignature=false', 'log', gitHash, '--pretty="%an <%ae>"'],
- workingDirectory: flutterRoot,
- ).first;
- return author;
-}
-
-String get ciUrl {
- switch (ciProvider) {
- case CiProviders.cirrus:
- return 'https://cirrus-ci.com/task/${Platform.environment['CIRRUS_TASK_ID']}';
- case CiProviders.luci:
- return 'https://ci.chromium.org/p/flutter/g/framework/console'; // TODO(dnfield): can we get a direct link to the actual build?
- }
- return '';
-}
-
-String get gitHash {
- switch(ciProvider) {
- case CiProviders.cirrus:
- return Platform.environment['CIRRUS_CHANGE_IN_REPO'];
- case CiProviders.luci:
- return 'HEAD'; // TODO(dnfield): Set this in the env for LUCI.
- }
- return '';
-}
-
-/// Checks the given file's contents to determine if they match the allowed
-/// pattern for version strings.
-///
-/// Returns null if the contents are good. Returns a string if they are bad.
-/// The string is an error message.
-Future<String> verifyVersion(File file) async {
- final RegExp pattern = RegExp(r'^\d+\.\d+\.\d+(\+hotfix\.\d+)?(-pre\.\d+)?$');
- final String version = await file.readAsString();
- if (!file.existsSync())
- return 'The version logic failed to create the Flutter version file.';
- if (version == '0.0.0-unknown')
- return 'The version logic failed to determine the Flutter version.';
- if (!version.contains(pattern))
- return 'The version logic generated an invalid version string: "$version".';
- return null;
-}
-
-/// If the CIRRUS_TASK_NAME environment variable exists, we use that to determine
-/// the shard and subshard (parsing it in the form shard-subshard-platform, ignoring
-/// the platform).
-///
-/// However, for local testing you can just set the SHARD and SUBSHARD
-/// environment variables. For example, to run all the framework tests you can
-/// just set SHARD=framework_tests. To run specifically the third subshard of
-/// the Web tests you can set SHARD=web_tests SUBSHARD=2 (it's zero-based).
-Future<void> selectShard(Map<String, ShardRunner> shards) => _runFromList(shards, 'SHARD', 'shard', 0);
-Future<void> selectSubshard(Map<String, ShardRunner> subshards) => _runFromList(subshards, 'SUBSHARD', 'subshard', 1);
-
-const String CIRRUS_TASK_NAME = 'CIRRUS_TASK_NAME';
-
-Future<void> _runFromList(Map<String, ShardRunner> items, String key, String name, int positionInTaskName) async {
- String item = Platform.environment[key];
- if (item == null && Platform.environment.containsKey(CIRRUS_TASK_NAME)) {
- final List<String> parts = Platform.environment[CIRRUS_TASK_NAME].split('-');
- assert(positionInTaskName < parts.length);
- item = parts[positionInTaskName];
- }
- if (item == null) {
- for (String currentItem in items.keys) {
- print('$bold$key=$currentItem$reset');
- await items[currentItem]();
- print('');
- }
- } else {
+Future<void> _runFromList(Map<String, ShardRunner> items, String key, String name) async {
+ final String item = Platform.environment[key];
+ if (item != null) {
if (!items.containsKey(item)) {
print('${red}Invalid $name: $item$reset');
print('The available ${name}s are: ${items.keys.join(", ")}');
@@ -996,5 +987,11 @@
}
print('$bold$key=$item$reset');
await items[item]();
+ } else {
+ for (String currentItem in items.keys) {
+ print('$bold$key=$currentItem$reset');
+ await items[currentItem]();
+ print('');
+ }
}
}
diff --git a/dev/bots/test/bot_test.dart b/dev/bots/test/bot_test.dart
deleted file mode 100644
index 476280c..0000000
--- a/dev/bots/test/bot_test.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2017 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:io';
-
-import 'common.dart';
-
-void main() {
- test('BOT variable is set on bots', () {
- expect(Platform.environment['BOT'], 'true');
- });
-}
diff --git a/dev/bots/test/sdk_directory_has_space_test.dart b/dev/bots/test/sdk_directory_has_space_test.dart
deleted file mode 100644
index f48dbdb..0000000
--- a/dev/bots/test/sdk_directory_has_space_test.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 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:io';
-
-import 'package:path/path.dart' as path;
-
-import 'common.dart';
-
-void main() {
- test('We are in a directory with a space in it', () async {
- // The Flutter SDK should be in a directory with a space in it, to make sure
- // our tools support that.
- final String expectedName = Platform.environment['FLUTTER_SDK_PATH_WITH_SPACE'];
- expect(expectedName, 'flutter sdk');
- expect(expectedName, contains(' '));
- final List<String> parts = path.split(Directory.current.absolute.path);
- expect(parts.reversed.take(3), <String>['bots', 'dev', expectedName]);
- });
-}
diff --git a/dev/bots/test/test_test.dart b/dev/bots/test/test_test.dart
index 31df83f..a3abf6a 100644
--- a/dev/bots/test/test_test.dart
+++ b/dev/bots/test/test_test.dart
@@ -29,11 +29,7 @@
];
for (String version in valid_versions) {
when(file.readAsString()).thenAnswer((Invocation invocation) => Future<String>.value(version));
- expect(
- await verifyVersion(file),
- isNull,
- reason: '$version is valid but verifyVersionFile said it was bad',
- );
+ expect(await verifyVersion(version, file), isTrue, reason: '$version is invalid');
}
});
@@ -45,15 +41,10 @@
'1.2.3-pre',
'1.2.3-pre.1+hotfix.1',
' 1.2.3',
- '1.2.3-hotfix.1',
];
for (String version in invalid_versions) {
when(file.readAsString()).thenAnswer((Invocation invocation) => Future<String>.value(version));
- expect(
- await verifyVersion(file),
- 'The version logic generated an invalid version string: "$version".',
- reason: '$version is invalid but verifyVersionFile said it was fine',
- );
+ expect(await verifyVersion(version, file), isFalse);
}
});
});
diff --git a/packages/flutter_tools/dart_test.yaml b/packages/flutter_tools/dart_test.yaml
index 789a255..cd8c697 100644
--- a/packages/flutter_tools/dart_test.yaml
+++ b/packages/flutter_tools/dart_test.yaml
@@ -1,9 +1,5 @@
-# package:test configuration
-# https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md
-
-# Some of our tests take an absurdly long time to run, and on some
-# hosts they can take even longer due to the host suddenly being
-# overloaded. For this reason, we set the test timeout to
-# significantly more than it would be by default, and we never set the
-# timeouts in the tests themselves.
-timeout: 15m
+tags:
+ "no_coverage":
+ "create":
+ "integration":
+
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/ide_config_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/ide_config_test.dart
index 4cf3b17..abad543 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/ide_config_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/ide_config_test.dart
@@ -135,7 +135,7 @@
return _updateIdeConfig(
expectedContents: expectedContents,
);
- });
+ }, timeout: const Timeout.factor(2.0));
testUsingContext('creates non-existent files', () async {
final Map<String, String> templateManifest = _getManifest(
@@ -155,7 +155,7 @@
return _updateIdeConfig(
expectedContents: expectedContents,
);
- });
+ }, timeout: const Timeout.factor(2.0));
testUsingContext('overwrites existing files with --overwrite', () async {
final Map<String, String> templateManifest = _getManifest(
@@ -181,7 +181,7 @@
args: <String>['--overwrite'],
expectedContents: expectedContents,
);
- });
+ }, timeout: const Timeout.factor(2.0));
testUsingContext('only adds new templates without --overwrite', () async {
final Map<String, String> templateManifest = _getManifest(
@@ -212,7 +212,7 @@
args: <String>['--update-templates'],
expectedContents: expectedContents,
);
- });
+ }, timeout: const Timeout.factor(2.0));
testUsingContext('update all templates with --overwrite', () async {
final Map<String, String> templateManifest = _getManifest(
@@ -239,7 +239,7 @@
args: <String>['--update-templates', '--overwrite'],
expectedContents: expectedContents,
);
- });
+ }, timeout: const Timeout.factor(2.0));
testUsingContext('removes deleted imls with --overwrite', () async {
final Map<String, String> templateManifest = _getManifest(
@@ -275,7 +275,7 @@
args: <String>['--update-templates', '--overwrite'],
expectedContents: expectedContents,
);
- });
+ }, timeout: const Timeout.factor(2.0));
testUsingContext('removes deleted imls with --overwrite, including empty parent dirs', () async {
final Map<String, String> templateManifest = _getManifest(
@@ -316,7 +316,7 @@
args: <String>['--update-templates', '--overwrite'],
expectedContents: expectedContents,
);
- });
+ }, timeout: const Timeout.factor(2.0));
});
}
diff --git a/packages/flutter_tools/test/commands.shard/permeable/analyze_once_test.dart b/packages/flutter_tools/test/commands.shard/permeable/analyze_once_test.dart
index b1c2a8a..38b8980 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/analyze_once_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/analyze_once_test.dart
@@ -16,6 +16,9 @@
import '../../src/common.dart';
import '../../src/context.dart';
+/// Test case timeout for tests involving project analysis.
+const Timeout allowForSlowAnalyzeTests = Timeout.factor(5.0);
+
final Generator _kNoColorTerminalPlatform = () => FakePlatform.fromPlatform(const LocalPlatform())..stdoutSupportsAnsi = false;
final Map<Type, Generator> noColorTerminalOverride = <Type, Generator>{
Platform: _kNoColorTerminalPlatform,
@@ -51,7 +54,7 @@
],
);
expect(libMain.existsSync(), isTrue);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -62,7 +65,7 @@
arguments: <String>['analyze'],
statusTextContains: <String>['No issues found!'],
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForSlowAnalyzeTests, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -77,7 +80,6 @@
}, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
-
// Analyze in the current directory - no arguments
testUsingContext('working directory with errors', () async {
// Break the code to produce the "The parameter 'onPressed' is required" hint
@@ -108,7 +110,7 @@
exitMessageContains: '2 issues found.',
toolExit: true,
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForSlowAnalyzeTests, overrides: <Type, Generator>{
Pub: () => const Pub(),
...noColorTerminalOverride,
});
@@ -138,7 +140,7 @@
exitMessageContains: '3 issues found.',
toolExit: true,
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForSlowAnalyzeTests, overrides: <Type, Generator>{
Pub: () => const Pub(),
...noColorTerminalOverride
});
diff --git a/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart b/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart
index 8f0476e..224d406 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart
@@ -73,7 +73,7 @@
expect(await command.usageValues,
containsPair(CustomDimensions.commandBuildBundleIsModule, 'true'));
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('bundle getUsage indicate that project is not a module', () async {
final String projectPath = await createProject(tempDir,
@@ -83,7 +83,7 @@
expect(await command.usageValues,
containsPair(CustomDimensions.commandBuildBundleIsModule, 'false'));
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('bundle getUsage indicate the target platform', () async {
final String projectPath = await createProject(tempDir,
@@ -93,7 +93,7 @@
expect(await command.usageValues,
containsPair(CustomDimensions.commandBuildBundleTargetPlatform, 'android-arm'));
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('bundle fails to build for Windows if feature is disabled', () async {
fs.file('lib/main.dart').createSync(recursive: true);
diff --git a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
index 6165895..2056e49 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
@@ -78,7 +78,7 @@
],
);
return _runFlutterTest(projectDir);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -96,7 +96,7 @@
'ios/Runner/GeneratedPluginRegistrant.h',
],
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -118,9 +118,11 @@
'ios/',
]);
return _runFlutterTest(projectDir);
- }, overrides: <Type, Generator>{
- Pub: () => const Pub(),
- });
+ },
+ timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
+ Pub: () => const Pub(),
+ },
+ );
testUsingContext('cannot create a project if non-empty non-project directory exists with .metadata', () async {
await projectDir.absolute.childDirectory('blag').create(recursive: true);
@@ -136,7 +138,7 @@
'.ios/',
]),
throwsToolExit(message: 'Sorry, unable to detect the type of project to recreate'));
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
...noColorTerminalOverride,
});
@@ -162,7 +164,7 @@
'.ios/',
],
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -187,7 +189,7 @@
'.ios/',
],
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -212,7 +214,7 @@
'lib/flutter_project.dart',
],
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -243,7 +245,7 @@
'test/widget_test.dart',
],
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -265,7 +267,7 @@
'ios/Runner/main.m',
],
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -295,7 +297,7 @@
],
);
return _runFlutterTest(projectDir);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -317,7 +319,7 @@
],
);
return _runFlutterTest(projectDir.childDirectory('example'));
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -344,7 +346,7 @@
'example/ios/Runner/main.m',
],
);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('plugin project with custom org', () async {
return _createProject(
@@ -364,7 +366,7 @@
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
],
);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('plugin project with valid custom project name', () async {
return _createProject(
@@ -384,7 +386,7 @@
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
],
);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('plugin project with invalid custom project name', () async {
expect(
@@ -394,7 +396,7 @@
),
throwsToolExit(message: '"xyz.xyz" is not a valid Dart package name.'),
);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('legacy app project with-driver-test', () async {
return _createAndAnalyzeProject(
@@ -402,7 +404,7 @@
<String>['--with-driver-test', '--template=app'],
<String>['lib/main.dart'],
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -437,7 +439,7 @@
'android/',
'ios/',
]);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -461,7 +463,7 @@
final String actualContents = await fs.file(projectDir.path + '/android/gradle.properties').readAsString();
expect(actualContents.contains('useAndroidX'), true);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('non androidx app project', () async {
Cache.flutterRoot = '../..';
@@ -482,7 +484,7 @@
final String actualContents = await fs.file(projectDir.path + '/android/gradle.properties').readAsString();
expect(actualContents.contains('useAndroidX'), false);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('androidx is used by default in a module project', () async {
Cache.flutterRoot = '../..';
@@ -499,7 +501,7 @@
project.usesAndroidX,
true,
);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('non androidx module', () async {
Cache.flutterRoot = '../..';
@@ -516,7 +518,7 @@
project.usesAndroidX,
false,
);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('androidx is used by default in a plugin project', () async {
Cache.flutterRoot = '../..';
@@ -537,7 +539,7 @@
final String actualContents = await fs.file(projectDir.path + '/android/gradle.properties').readAsString();
expect(actualContents.contains('useAndroidX'), true);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('non androidx plugin project', () async {
Cache.flutterRoot = '../..';
@@ -558,7 +560,7 @@
final String actualContents = await fs.file(projectDir.path + '/android/gradle.properties').readAsString();
expect(actualContents.contains('useAndroidX'), false);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('app supports macOS if requested', () async {
Cache.flutterRoot = '../..';
@@ -571,7 +573,7 @@
await runner.run(<String>['create', '--no-pub', '--macos', projectDir.path]);
expect(projectDir.childDirectory('macos').childDirectory('Runner.xcworkspace').existsSync(), true);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('app does not include macOS by default', () async {
Cache.flutterRoot = '../..';
@@ -584,7 +586,7 @@
await runner.run(<String>['create', '--no-pub', projectDir.path]);
expect(projectDir.childDirectory('macos').childDirectory('Runner.xcworkspace').existsSync(), false);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('plugin supports macOS if requested', () async {
Cache.flutterRoot = '../..';
@@ -597,7 +599,7 @@
await runner.run(<String>['create', '--no-pub', '--template=plugin', '--macos', projectDir.path]);
expect(projectDir.childDirectory('macos').childFile('flutter_project.podspec').existsSync(), true);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('plugin does not include macOS by default', () async {
Cache.flutterRoot = '../..';
@@ -610,7 +612,7 @@
await runner.run(<String>['create', '--no-pub', '--template=plugin', projectDir.path]);
expect(projectDir.childDirectory('macos').childFile('flutter_project.podspec').existsSync(), false);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('has correct content and formatting with module template', () async {
Cache.flutterRoot = '../..';
@@ -706,7 +708,7 @@
}, overrides: <Type, Generator>{
FlutterVersion: () => mockFlutterVersion,
Platform: _kNoColorTerminalPlatform,
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('has correct content and formatting with app template', () async {
Cache.flutterRoot = '../..';
@@ -777,7 +779,7 @@
}, overrides: <Type, Generator>{
FlutterVersion: () => mockFlutterVersion,
Platform: _kNoColorTerminalPlatform,
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('has correct application id for android and bundle id for ios', () async {
Cache.flutterRoot = '../..';
@@ -825,7 +827,7 @@
}, overrides: <Type, Generator>{
FlutterVersion: () => mockFlutterVersion,
Platform: _kNoColorTerminalPlatform,
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('can re-gen default template over existing project', () async {
Cache.flutterRoot = '../..';
@@ -839,7 +841,7 @@
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
expect(metadata, contains('project_type: app\n'));
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('can re-gen default template over existing app project with no metadta and detect the type', () async {
Cache.flutterRoot = '../..';
@@ -856,7 +858,7 @@
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
expect(metadata, contains('project_type: app\n'));
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('can re-gen app template over existing app project and detect the type', () async {
Cache.flutterRoot = '../..';
@@ -870,7 +872,7 @@
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
expect(metadata, contains('project_type: app\n'));
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('can re-gen template over existing module project and detect the type', () async {
Cache.flutterRoot = '../..';
@@ -884,7 +886,7 @@
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
expect(metadata, contains('project_type: module\n'));
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('can re-gen default template over existing plugin project and detect the type', () async {
Cache.flutterRoot = '../..';
@@ -898,7 +900,7 @@
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
expect(metadata, contains('project_type: plugin'));
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('can re-gen default template over existing package project and detect the type', () async {
Cache.flutterRoot = '../..';
@@ -912,7 +914,7 @@
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
expect(metadata, contains('project_type: package'));
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('can re-gen module .android/ folder, reusing custom org', () async {
await _createProject(
@@ -928,7 +930,7 @@
'.android/app/src/main/java/com/bar/foo/flutter_project/host/MainActivity.java',
],
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -945,7 +947,7 @@
await project.ios.productBundleIdentifier,
'com.bar.foo.flutterProject',
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -972,7 +974,7 @@
'android/app/src/main/java/com/example/flutter_project/MainActivity.java',
],
);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('can re-gen app ios/ folder, reusing custom org', () async {
await _createProject(
@@ -987,7 +989,7 @@
await project.ios.productBundleIdentifier,
'com.bar.foo.flutterProject',
);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('can re-gen plugin ios/ and example/ folders, reusing custom org', () async {
await _createProject(
@@ -1020,7 +1022,7 @@
await project.example.ios.productBundleIdentifier,
'com.bar.foo.flutterProjectExample',
);
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('fails to re-gen without specified org when org is ambiguous', () async {
await _createProject(
@@ -1038,7 +1040,7 @@
() => _createProject(projectDir, <String>[], <String>[]),
throwsToolExit(message: 'Ambiguous organization'),
);
- });
+ }, timeout: allowForCreateFlutterProject);
// Verify that we help the user correct an option ordering issue
testUsingContext('produces sensible error message', () async {
@@ -1100,7 +1102,7 @@
'ios/Runner/GeneratedPluginRegistrant.h',
],
);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -1126,6 +1128,7 @@
expect(loggingProcessManager.commands.first, contains(matches(r'dart-sdk[\\/]bin[\\/]pub')));
expect(loggingProcessManager.commands.first, contains('--offline'));
},
+ timeout: allowForCreateFlutterProject,
overrides: <Type, Generator>{
ProcessManager: () => loggingProcessManager,
Pub: () => const Pub(),
@@ -1144,6 +1147,7 @@
expect(loggingProcessManager.commands.first, contains(matches(r'dart-sdk[\\/]bin[\\/]pub')));
expect(loggingProcessManager.commands.first, isNot(contains('--offline')));
},
+ timeout: allowForCreateFlutterProject,
overrides: <Type, Generator>{
ProcessManager: () => loggingProcessManager,
Pub: () => const Pub(),
@@ -1164,7 +1168,7 @@
);
expect(projectDir.childDirectory('lib').childFile('main.dart').readAsStringSync(),
contains('void main() {}'));
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
HttpClientFactory: () => () => MockHttpClient(200, result: 'void main() {}'),
});
diff --git a/packages/flutter_tools/test/commands.shard/permeable/packages_test.dart b/packages/flutter_tools/test/commands.shard/permeable/packages_test.dart
index a9197ed..07da823 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/packages_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/packages_test.dart
@@ -207,7 +207,7 @@
expectDependenciesResolved(projectPath);
expectZeroPluginsInjected(projectPath);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -220,7 +220,7 @@
expectDependenciesResolved(projectPath);
expectZeroPluginsInjected(projectPath);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -234,7 +234,7 @@
expect(await getCommand.usageValues,
containsPair(CustomDimensions.commandPackagesNumberPlugins, '0'));
- }, overrides: <Type, Generator>{
+ }, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -248,7 +248,7 @@
expect(await getCommand.usageValues,
containsPair(CustomDimensions.commandPackagesProjectModule, 'false'));
- }, overrides: <Type, Generator>{
+ }, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -262,7 +262,7 @@
expect(await getCommand.usageValues,
containsPair(CustomDimensions.commandPackagesProjectModule, 'true'));
- }, overrides: <Type, Generator>{
+ }, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -275,7 +275,7 @@
expectDependenciesResolved(projectPath);
expectZeroPluginsInjected(projectPath);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -288,7 +288,7 @@
expectDependenciesResolved(projectPath);
expectModulePluginInjected(projectPath);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
@@ -309,7 +309,7 @@
expectDependenciesResolved(exampleProjectPath);
expectPluginInjected(exampleProjectPath);
- }, overrides: <Type, Generator>{
+ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
});
diff --git a/packages/flutter_tools/test/general.shard/commands/build_aar_test.dart b/packages/flutter_tools/test/general.shard/commands/build_aar_test.dart
index a93b50e..1591e75 100644
--- a/packages/flutter_tools/test/general.shard/commands/build_aar_test.dart
+++ b/packages/flutter_tools/test/general.shard/commands/build_aar_test.dart
@@ -57,7 +57,7 @@
}, overrides: <Type, Generator>{
AndroidBuilder: () => FakeAndroidBuilder(),
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('indicate that project is a plugin', () async {
final String projectPath = await createProject(tempDir,
@@ -69,7 +69,7 @@
}, overrides: <Type, Generator>{
AndroidBuilder: () => FakeAndroidBuilder(),
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('indicate the target platform', () async {
final String projectPath = await createProject(tempDir,
@@ -82,7 +82,7 @@
}, overrides: <Type, Generator>{
AndroidBuilder: () => FakeAndroidBuilder(),
- });
+ }, timeout: allowForCreateFlutterProject);
});
group('Gradle', () {
diff --git a/packages/flutter_tools/test/general.shard/commands/build_apk_test.dart b/packages/flutter_tools/test/general.shard/commands/build_apk_test.dart
index 05fa1ff..a67c9fa 100644
--- a/packages/flutter_tools/test/general.shard/commands/build_apk_test.dart
+++ b/packages/flutter_tools/test/general.shard/commands/build_apk_test.dart
@@ -48,7 +48,7 @@
}, overrides: <Type, Generator>{
AndroidBuilder: () => FakeAndroidBuilder(),
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('split per abi', () async {
final String projectPath = await createProject(tempDir,
@@ -65,7 +65,7 @@
}, overrides: <Type, Generator>{
AndroidBuilder: () => FakeAndroidBuilder(),
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('build type', () async {
final String projectPath = await createProject(tempDir,
@@ -92,7 +92,7 @@
}, overrides: <Type, Generator>{
AndroidBuilder: () => FakeAndroidBuilder(),
- });
+ }, timeout: allowForCreateFlutterProject);
});
group('Gradle', () {
@@ -223,7 +223,8 @@
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
- });
+ },
+ timeout: allowForCreateFlutterProject);
testUsingContext('shrinking is disabled when --no-shrink is passed', () async {
final String projectPath = await createProject(tempDir,
@@ -254,7 +255,8 @@
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
- });
+ },
+ timeout: allowForCreateFlutterProject);
testUsingContext('guides the user when the shrinker fails', () async {
final String projectPath = await createProject(tempDir,
@@ -310,7 +312,8 @@
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage,
- });
+ },
+ timeout: allowForCreateFlutterProject);
testUsingContext('reports when the app isn\'t using AndroidX', () async {
final String projectPath = await createProject(tempDir,
@@ -363,7 +366,8 @@
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage,
- });
+ },
+ timeout: allowForCreateFlutterProject);
testUsingContext('reports when the app is using AndroidX', () async {
final String projectPath = await createProject(tempDir,
@@ -418,7 +422,8 @@
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage,
- });
+ },
+ timeout: allowForCreateFlutterProject);
});
}
diff --git a/packages/flutter_tools/test/general.shard/commands/build_appbundle_test.dart b/packages/flutter_tools/test/general.shard/commands/build_appbundle_test.dart
index 7663156..a00d279 100644
--- a/packages/flutter_tools/test/general.shard/commands/build_appbundle_test.dart
+++ b/packages/flutter_tools/test/general.shard/commands/build_appbundle_test.dart
@@ -48,7 +48,7 @@
}, overrides: <Type, Generator>{
AndroidBuilder: () => FakeAndroidBuilder(),
- });
+ }, timeout: allowForCreateFlutterProject);
testUsingContext('build type', () async {
final String projectPath = await createProject(tempDir,
@@ -75,7 +75,7 @@
}, overrides: <Type, Generator>{
AndroidBuilder: () => FakeAndroidBuilder(),
- });
+ }, timeout: allowForCreateFlutterProject);
});
group('Gradle', () {
@@ -212,7 +212,8 @@
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
- });
+ },
+ timeout: allowForCreateFlutterProject);
testUsingContext('shrinking is disabled when --no-shrink is passed', () async {
final String projectPath = await createProject(
@@ -245,7 +246,8 @@
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
- });
+ },
+ timeout: allowForCreateFlutterProject);
testUsingContext('guides the user when the shrinker fails', () async {
final String projectPath = await createProject(tempDir,
@@ -301,7 +303,8 @@
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage,
- });
+ },
+ timeout: allowForCreateFlutterProject);
testUsingContext('reports when the app isn\'t using AndroidX', () async {
final String projectPath = await createProject(tempDir,
@@ -354,7 +357,8 @@
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage,
- });
+ },
+ timeout: allowForCreateFlutterProject);
testUsingContext('reports when the app is using AndroidX', () async {
final String projectPath = await createProject(tempDir,
@@ -409,7 +413,8 @@
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage,
- });
+ },
+ timeout: allowForCreateFlutterProject);
});
}
diff --git a/packages/flutter_tools/test/integration.shard/daemon_mode_test.dart b/packages/flutter_tools/test/integration.shard/daemon_mode_test.dart
index aee21d0..f1ce5ba 100644
--- a/packages/flutter_tools/test/integration.shard/daemon_mode_test.dart
+++ b/packages/flutter_tools/test/integration.shard/daemon_mode_test.dart
@@ -2,9 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Integration tests which invoke flutter instead of unit testing the code
+// will not produce meaningful coverage information - we can measure coverage
+// from the isolate running the test, but not from the isolate started via
+// the command line process.
+@Tags(<String>['no_coverage'])
import 'dart:async';
import 'dart:convert';
-import 'dart:io';
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
@@ -17,58 +21,79 @@
import 'test_utils.dart';
void main() {
- test('device.getDevices', () async {
- final Directory tempDir = createResolvedTempDirectorySync('daemon_mode_test.');
-
+ group('daemon_mode', () {
+ Directory tempDir;
final BasicProject _project = BasicProject();
- await _project.setUpIn(tempDir);
+ Process process;
- final String flutterBin = fs.path.join(getFlutterRoot(), 'bin', 'flutter');
+ setUp(() async {
+ tempDir = createResolvedTempDirectorySync('daemon_mode_test.');
+ await _project.setUpIn(tempDir);
+ });
- const ProcessManager processManager = LocalProcessManager();
- final Process process = await processManager.start(
- <String>[flutterBin, '--show-test-device', 'daemon'],
- workingDirectory: tempDir.path,
- );
+ tearDown(() async {
+ tryToDelete(tempDir);
+ process?.kill();
+ });
- final StreamController<String> stdout = StreamController<String>.broadcast();
- transformToLines(process.stdout).listen((String line) => stdout.add(line));
- final Stream<Map<String, dynamic>> stream = stdout
- .stream
- .map<Map<String, dynamic>>(parseFlutterResponse)
- .where((Map<String, dynamic> value) => value != null);
+ test('device.getDevices', () async {
+ final String flutterBin =
+ fs.path.join(getFlutterRoot(), 'bin', 'flutter');
- Map<String, dynamic> response = await stream.first;
- expect(response['event'], 'daemon.connected');
+ const ProcessManager processManager = LocalProcessManager();
+ process = await processManager.start(
+ <String>[flutterBin, '--show-test-device', 'daemon'],
+ workingDirectory: tempDir.path);
- // start listening for devices
- process.stdin.writeln('[${jsonEncode(<String, dynamic>{
- 'id': 1,
- 'method': 'device.enable',
- })}]');
- response = await stream.first;
- expect(response['id'], 1);
- expect(response['error'], isNull);
+ final StreamController<String> stdout =
+ StreamController<String>.broadcast();
- // [{"event":"device.added","params":{"id":"flutter-tester","name":
- // "Flutter test device","platform":"flutter-tester","emulator":false}}]
- response = await stream.first;
- expect(response['event'], 'device.added');
+ transformToLines(process.stdout)
+ .listen((String line) => stdout.add(line));
- // get the list of all devices
- process.stdin.writeln('[${jsonEncode(<String, dynamic>{
- 'id': 2,
- 'method': 'device.getDevices',
- })}]');
- response = await stream.first;
- expect(response['id'], 2);
- expect(response['error'], isNull);
+ final Stream<Map<String, dynamic>> stream =
+ stdout.stream.where((String line) {
+ final Map<String, dynamic> response = parseFlutterResponse(line);
+ // ignore 'Starting device daemon...'
+ if (response == null) {
+ return false;
+ }
+ // TODO(devoncarew): Remove this after #25440 lands.
+ if (response['event'] == 'daemon.showMessage') {
+ return false;
+ }
+ return true;
+ }).map(parseFlutterResponse);
- final dynamic result = response['result'];
- expect(result, isList);
- expect(result, isNotEmpty);
+ Map<String, dynamic> response = await stream.first;
+ expect(response['event'], 'daemon.connected');
- tryToDelete(tempDir);
- process.kill();
- });
+ // start listening for devices
+ process.stdin.writeln('[${jsonEncode(<String, dynamic>{
+ 'id': 1,
+ 'method': 'device.enable',
+ })}]');
+ response = await stream.first;
+ expect(response['id'], 1);
+ expect(response['error'], isNull);
+
+ // [{"event":"device.added","params":{"id":"flutter-tester","name":
+ // "Flutter test device","platform":"flutter-tester","emulator":false}}]
+ response = await stream.first;
+ expect(response['event'], 'device.added');
+
+ // get the list of all devices
+ process.stdin.writeln('[${jsonEncode(<String, dynamic>{
+ 'id': 2,
+ 'method': 'device.getDevices',
+ })}]');
+ response = await stream.first;
+ expect(response['id'], 2);
+ expect(response['error'], isNull);
+
+ final dynamic result = response['result'];
+ expect(result, isList);
+ expect(result, isNotEmpty);
+ });
+ }, timeout: const Timeout.factor(10), tags: <String>['integration']); // This test uses the `flutter` tool, which could be blocked behind the startup lock for a long time.
}
diff --git a/packages/flutter_tools/test/integration.shard/debugger_stepping_test.dart b/packages/flutter_tools/test/integration.shard/debugger_stepping_test.dart
index e6a743c..a53cff9 100644
--- a/packages/flutter_tools/test/integration.shard/debugger_stepping_test.dart
+++ b/packages/flutter_tools/test/integration.shard/debugger_stepping_test.dart
@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:io';
-
+// Integration tests which invoke flutter instead of unit testing the code
+// will not produce meaningful coverage information - we can measure coverage
+// from the isolate running the test, but not from the isolate started via
+// the command line process.
+@Tags(<String>['no_coverage'])
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
@@ -13,37 +16,43 @@
import 'test_utils.dart';
void main() {
- test('can step over statements', () async {
- final Directory tempDir = createResolvedTempDirectorySync('debugger_stepping_test.');
-
+ group('debugger', () {
+ Directory tempDir;
final SteppingProject _project = SteppingProject();
- await _project.setUpIn(tempDir);
+ FlutterRunTestDriver _flutter;
- final FlutterRunTestDriver _flutter = FlutterRunTestDriver(tempDir);
+ setUp(() async {
+ tempDir = createResolvedTempDirectorySync('debugger_stepping_test.');
+ await _project.setUpIn(tempDir);
+ _flutter = FlutterRunTestDriver(tempDir);
+ });
- await _flutter.run(withDebugger: true, startPaused: true);
- await _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine);
- await _flutter.resume();
- await _flutter.waitForPause(); // Now we should be on the breakpoint.
+ tearDown(() async {
+ await _flutter.stop();
+ tryToDelete(tempDir);
+ });
- expect((await _flutter.getSourceLocation()).line, equals(_project.breakpointLine));
+ test('can step over statements', () async {
+ await _flutter.run(withDebugger: true, startPaused: true);
+ await _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine);
+ await _flutter.resume();
+ await _flutter.waitForPause(); // Now we should be on the breakpoint.
- // Issue 5 steps, ensuring that we end up on the annotated lines each time.
- for (int i = 1; i <= _project.numberOfSteps; i += 1) {
- await _flutter.stepOverOrOverAsyncSuspension();
- final SourcePosition location = await _flutter.getSourceLocation();
- final int actualLine = location.line;
+ expect((await _flutter.getSourceLocation()).line, equals(_project.breakpointLine));
- // Get the line we're expected to stop at by searching for the comment
- // within the source code.
- final int expectedLine = _project.lineForStep(i);
+ // Issue 5 steps, ensuring that we end up on the annotated lines each time.
+ for (int i = 1; i <= _project.numberOfSteps; i += 1) {
+ await _flutter.stepOverOrOverAsyncSuspension();
+ final SourcePosition location = await _flutter.getSourceLocation();
+ final int actualLine = location.line;
- expect(actualLine, equals(expectedLine),
- reason: 'After $i steps, debugger should stop at $expectedLine but stopped at $actualLine'
- );
- }
+ // Get the line we're expected to stop at by searching for the comment
+ // within the source code.
+ final int expectedLine = _project.lineForStep(i);
- await _flutter.stop();
- tryToDelete(tempDir);
- });
+ expect(actualLine, equals(expectedLine),
+ reason: 'After $i steps, debugger should stop at $expectedLine but stopped at $actualLine');
+ }
+ });
+ }, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
}
diff --git a/packages/flutter_tools/test/integration.shard/expression_evaluation_test.dart b/packages/flutter_tools/test/integration.shard/expression_evaluation_test.dart
index 00038a8..a15dad4 100644
--- a/packages/flutter_tools/test/integration.shard/expression_evaluation_test.dart
+++ b/packages/flutter_tools/test/integration.shard/expression_evaluation_test.dart
@@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Integration tests which invoke flutter instead of unit testing the code
+// will not produce meaningful coverage information - we can measure coverage
+// from the isolate running the test, but not from the isolate started via
+// the command line process.
+@Tags(<String>['no_coverage'])
import 'dart:async';
-import 'dart:io';
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
@@ -16,133 +20,120 @@
import 'test_driver.dart';
import 'test_utils.dart';
-void batch1() {
- final BasicProject _project = BasicProject();
- Directory tempDir;
- FlutterRunTestDriver _flutter;
+void main() {
+ group('flutter run expression evaluation', () {
+ Directory tempDir;
+ final BasicProject _project = BasicProject();
+ FlutterRunTestDriver _flutter;
- Future<void> initProject() async {
- tempDir = createResolvedTempDirectorySync('run_expression_eval_test.');
- await _project.setUpIn(tempDir);
- _flutter = FlutterRunTestDriver(tempDir);
- }
+ setUp(() async {
+ tempDir = createResolvedTempDirectorySync('run_expression_eval_test.');
+ await _project.setUpIn(tempDir);
+ _flutter = FlutterRunTestDriver(tempDir);
+ });
- Future<void> cleanProject() async {
- await _flutter.stop();
- tryToDelete(tempDir);
- }
+ tearDown(() async {
+ await _flutter.stop();
+ tryToDelete(tempDir);
+ });
- Future<void> breakInBuildMethod(FlutterTestDriver flutter) async {
- await _flutter.breakAt(
- _project.buildMethodBreakpointUri,
- _project.buildMethodBreakpointLine,
- );
- }
+ Future<void> breakInBuildMethod(FlutterTestDriver flutter) async {
+ await _flutter.breakAt(
+ _project.buildMethodBreakpointUri,
+ _project.buildMethodBreakpointLine,
+ );
+ }
- Future<void> breakInTopLevelFunction(FlutterTestDriver flutter) async {
- await _flutter.breakAt(
- _project.topLevelFunctionBreakpointUri,
- _project.topLevelFunctionBreakpointLine,
- );
- }
+ Future<void> breakInTopLevelFunction(FlutterTestDriver flutter) async {
+ await _flutter.breakAt(
+ _project.topLevelFunctionBreakpointUri,
+ _project.topLevelFunctionBreakpointLine,
+ );
+ }
- test('flutter run expression evaluation - can evaluate trivial expressions in top level function', () async {
- await initProject();
- await _flutter.run(withDebugger: true);
- await breakInTopLevelFunction(_flutter);
- await evaluateTrivialExpressions(_flutter);
- await cleanProject();
- });
+ test('can evaluate trivial expressions in top level function', () async {
+ await _flutter.run(withDebugger: true);
+ await breakInTopLevelFunction(_flutter);
+ await evaluateTrivialExpressions(_flutter);
+ });
- test('flutter run expression evaluation - can evaluate trivial expressions in build method', () async {
- await initProject();
- await _flutter.run(withDebugger: true);
- await breakInBuildMethod(_flutter);
- await evaluateTrivialExpressions(_flutter);
- await cleanProject();
- });
+ test('can evaluate trivial expressions in build method', () async {
+ await _flutter.run(withDebugger: true);
+ await breakInBuildMethod(_flutter);
+ await evaluateTrivialExpressions(_flutter);
+ });
- test('flutter run expression evaluation - can evaluate complex expressions in top level function', () async {
- await initProject();
- await _flutter.run(withDebugger: true);
- await breakInTopLevelFunction(_flutter);
- await evaluateComplexExpressions(_flutter);
- await cleanProject();
- });
+ test('can evaluate complex expressions in top level function', () async {
+ await _flutter.run(withDebugger: true);
+ await breakInTopLevelFunction(_flutter);
+ await evaluateComplexExpressions(_flutter);
+ });
- test('flutter run expression evaluation - can evaluate complex expressions in build method', () async {
- await initProject();
- await _flutter.run(withDebugger: true);
- await breakInBuildMethod(_flutter);
- await evaluateComplexExpressions(_flutter);
- await cleanProject();
- });
+ test('can evaluate complex expressions in build method', () async {
+ await _flutter.run(withDebugger: true);
+ await breakInBuildMethod(_flutter);
+ await evaluateComplexExpressions(_flutter);
+ });
- test('flutter run expression evaluation - can evaluate expressions returning complex objects in top level function', () async {
- await initProject();
- await _flutter.run(withDebugger: true);
- await breakInTopLevelFunction(_flutter);
- await evaluateComplexReturningExpressions(_flutter);
- await cleanProject();
- });
+ test('can evaluate expressions returning complex objects in top level function', () async {
+ await _flutter.run(withDebugger: true);
+ await breakInTopLevelFunction(_flutter);
+ await evaluateComplexReturningExpressions(_flutter);
+ });
- test('flutter run expression evaluation - can evaluate expressions returning complex objects in build method', () async {
- await initProject();
- await _flutter.run(withDebugger: true);
- await breakInBuildMethod(_flutter);
- await evaluateComplexReturningExpressions(_flutter);
- await cleanProject();
- });
-}
+ test('can evaluate expressions returning complex objects in build method', () async {
+ await _flutter.run(withDebugger: true);
+ await breakInBuildMethod(_flutter);
+ await evaluateComplexReturningExpressions(_flutter);
+ });
+ }, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
-void batch2() {
- final TestsProject _project = TestsProject();
- Directory tempDir;
- FlutterTestTestDriver _flutter;
+ group('flutter test expression evaluation', () {
+ Directory tempDir;
+ final TestsProject _project = TestsProject();
+ FlutterTestTestDriver _flutter;
- Future<void> initProject() async {
- tempDir = createResolvedTempDirectorySync('test_expression_eval_test.');
- await _project.setUpIn(tempDir);
- _flutter = FlutterTestTestDriver(tempDir);
- }
+ setUp(() async {
+ tempDir = createResolvedTempDirectorySync('test_expression_eval_test.');
+ await _project.setUpIn(tempDir);
+ _flutter = FlutterTestTestDriver(tempDir);
+ });
- Future<void> cleanProject() async {
- await _flutter?.quit();
- tryToDelete(tempDir);
- }
+ tearDown(() async {
+ await _flutter.quit();
+ tryToDelete(tempDir);
+ });
- test('flutter test expression evaluation - can evaluate trivial expressions in a test', () async {
- await initProject();
- await _flutter.test(
- withDebugger: true,
- beforeStart: () => _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine),
- );
- await _flutter.waitForPause();
- await evaluateTrivialExpressions(_flutter);
- await cleanProject();
- });
+ test('can evaluate trivial expressions in a test', () async {
+ await _flutter.test(
+ withDebugger: true,
+ beforeStart: () => _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine),
+ );
+ await _flutter.waitForPause();
+ await evaluateTrivialExpressions(_flutter);
+ await _flutter.resume();
+ });
- test('flutter test expression evaluation - can evaluate complex expressions in a test', () async {
- await initProject();
- await _flutter.test(
- withDebugger: true,
- beforeStart: () => _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine),
- );
- await _flutter.waitForPause();
- await evaluateComplexExpressions(_flutter);
- await cleanProject();
- });
+ test('can evaluate complex expressions in a test', () async {
+ await _flutter.test(
+ withDebugger: true,
+ beforeStart: () => _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine),
+ );
+ await _flutter.waitForPause();
+ await evaluateComplexExpressions(_flutter);
+ await _flutter.resume();
+ });
- test('flutter test expression evaluation - can evaluate expressions returning complex objects in a test', () async {
- await initProject();
- await _flutter.test(
- withDebugger: true,
- beforeStart: () => _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine),
- );
- await _flutter.waitForPause();
- await evaluateComplexReturningExpressions(_flutter);
- await cleanProject();
- });
+ test('can evaluate expressions returning complex objects in a test', () async {
+ await _flutter.test(
+ withDebugger: true,
+ beforeStart: () => _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine),
+ );
+ await _flutter.waitForPause();
+ await evaluateComplexReturningExpressions(_flutter);
+ await _flutter.resume();
+ });
+ }, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
}
Future<void> evaluateTrivialExpressions(FlutterTestDriver flutter) async {
@@ -173,8 +164,3 @@
final InstanceRef res = await flutter.evaluate(resp.id, r'"$year-$month-$day"');
expect(res.valueAsString, equals('${now.year}-${now.month}-${now.day}'));
}
-
-void main() {
- batch1();
- batch2();
-}
diff --git a/packages/flutter_tools/test/integration.shard/flutter_attach_test.dart b/packages/flutter_tools/test/integration.shard/flutter_attach_test.dart
index 2d868b3..b5592c1 100644
--- a/packages/flutter_tools/test/integration.shard/flutter_attach_test.dart
+++ b/packages/flutter_tools/test/integration.shard/flutter_attach_test.dart
@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:io';
-
+// Integration tests which invoke flutter instead of unit testing the code
+// will not produce meaningful coverage information - we can measure coverage
+// from the isolate running the test, but not from the isolate started via
+// the command line process.
+@Tags(<String>['no_coverage'])
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
@@ -30,36 +33,35 @@
tryToDelete(tempDir);
});
- test('writes pid-file', () async {
- final File pidFile = tempDir.childFile('test.pid');
- await _flutterRun.run(withDebugger: true);
- await _flutterAttach.attach(
- _flutterRun.vmServicePort,
- pidFile: pidFile,
- );
- expect(pidFile.existsSync(), isTrue);
- });
-
- test('can hot reload', () async {
- await _flutterRun.run(withDebugger: true);
- await _flutterAttach.attach(_flutterRun.vmServicePort);
- await _flutterAttach.hotReload();
- });
-
- test('can detach, reattach, hot reload', () async {
- await _flutterRun.run(withDebugger: true);
- await _flutterAttach.attach(_flutterRun.vmServicePort);
- await _flutterAttach.detach();
- await _flutterAttach.attach(_flutterRun.vmServicePort);
- await _flutterAttach.hotReload();
- });
-
- test('killing process behaves the same as detach ', () async {
- await _flutterRun.run(withDebugger: true);
- await _flutterAttach.attach(_flutterRun.vmServicePort);
- await _flutterAttach.quit();
- _flutterAttach = FlutterRunTestDriver(tempDir, logPrefix: 'ATTACH-2');
- await _flutterAttach.attach(_flutterRun.vmServicePort);
- await _flutterAttach.hotReload();
- });
+ group('attached process', () {
+ test('writes pid-file', () async {
+ final File pidFile = tempDir.childFile('test.pid');
+ await _flutterRun.run(withDebugger: true);
+ await _flutterAttach.attach(
+ _flutterRun.vmServicePort,
+ pidFile: pidFile,
+ );
+ expect(pidFile.existsSync(), isTrue);
+ });
+ test('can hot reload', () async {
+ await _flutterRun.run(withDebugger: true);
+ await _flutterAttach.attach(_flutterRun.vmServicePort);
+ await _flutterAttach.hotReload();
+ });
+ test('can detach, reattach, hot reload', () async {
+ await _flutterRun.run(withDebugger: true);
+ await _flutterAttach.attach(_flutterRun.vmServicePort);
+ await _flutterAttach.detach();
+ await _flutterAttach.attach(_flutterRun.vmServicePort);
+ await _flutterAttach.hotReload();
+ });
+ test('killing process behaves the same as detach ', () async {
+ await _flutterRun.run(withDebugger: true);
+ await _flutterAttach.attach(_flutterRun.vmServicePort);
+ await _flutterAttach.quit();
+ _flutterAttach = FlutterRunTestDriver(tempDir, logPrefix: 'ATTACH-2');
+ await _flutterAttach.attach(_flutterRun.vmServicePort);
+ await _flutterAttach.hotReload();
+ });
+ }, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
}
diff --git a/packages/flutter_tools/test/integration.shard/flutter_run_test.dart b/packages/flutter_tools/test/integration.shard/flutter_run_test.dart
index 32f50e1..cc83323 100644
--- a/packages/flutter_tools/test/integration.shard/flutter_run_test.dart
+++ b/packages/flutter_tools/test/integration.shard/flutter_run_test.dart
@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Integration tests which invoke flutter instead of unit testing the code
+// will not produce meaningful coverage information - we can measure coverage
+// from the isolate running the test, but not from the isolate started via
+// the command line process.
+@Tags(<String>['no_coverage'])
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
@@ -13,45 +18,47 @@
import 'test_utils.dart';
void main() {
- Directory tempDir;
- final BasicProject _project = BasicProject();
- FlutterRunTestDriver _flutter;
+ group('flutter_run', () {
+ Directory tempDir;
+ final BasicProject _project = BasicProject();
+ FlutterRunTestDriver _flutter;
- setUp(() async {
- tempDir = createResolvedTempDirectorySync('run_test.');
- await _project.setUpIn(tempDir);
- _flutter = FlutterRunTestDriver(tempDir);
- });
+ setUp(() async {
+ tempDir = createResolvedTempDirectorySync('run_test.');
+ await _project.setUpIn(tempDir);
+ _flutter = FlutterRunTestDriver(tempDir);
+ });
- tearDown(() async {
- await _flutter.stop();
- tryToDelete(tempDir);
- });
+ tearDown(() async {
+ await _flutter.stop();
+ tryToDelete(tempDir);
+ });
- test('flutter run reports an error if an invalid device is supplied', () async {
- // This test forces flutter to check for all possible devices to catch issues
- // like https://github.com/flutter/flutter/issues/21418 which were skipped
- // over because other integration tests run using flutter-tester which short-cuts
- // some of the checks for devices.
- final String flutterBin = fs.path.join(getFlutterRoot(), 'bin', 'flutter');
+ test('reports an error if an invalid device is supplied', () async {
+ // This test forces flutter to check for all possible devices to catch issues
+ // like https://github.com/flutter/flutter/issues/21418 which were skipped
+ // over because other integration tests run using flutter-tester which short-cuts
+ // some of the checks for devices.
+ final String flutterBin = fs.path.join(getFlutterRoot(), 'bin', 'flutter');
- const ProcessManager _processManager = LocalProcessManager();
- final ProcessResult _proc = await _processManager.run(
- <String>[flutterBin, 'run', '-d', 'invalid-device-id'],
- workingDirectory: tempDir.path,
- );
+ const ProcessManager _processManager = LocalProcessManager();
+ final ProcessResult _proc = await _processManager.run(
+ <String>[flutterBin, 'run', '-d', 'invalid-device-id'],
+ workingDirectory: tempDir.path,
+ );
- expect(_proc.stdout, isNot(contains('flutter has exited unexpectedly')));
- expect(_proc.stderr, isNot(contains('flutter has exited unexpectedly')));
- if (!_proc.stderr.toString().contains('Unable to locate a development')
- && !_proc.stdout.toString().contains('No devices found with name or id matching')) {
- fail("'flutter run -d invalid-device-id' did not produce the expected error");
- }
- });
+ expect(_proc.stdout, isNot(contains('flutter has exited unexpectedly')));
+ expect(_proc.stderr, isNot(contains('flutter has exited unexpectedly')));
+ if (!_proc.stderr.toString().contains('Unable to locate a development')
+ && !_proc.stdout.toString().contains('No devices found with name or id matching')) {
+ fail("'flutter run -d invalid-device-id' did not produce the expected error");
+ }
+ });
- test('flutter run writes pid-file', () async {
- final File pidFile = tempDir.childFile('test.pid');
- await _flutter.run(pidFile: pidFile);
- expect(pidFile.existsSync(), isTrue);
- });
+ test('writes pid-file', () async {
+ final File pidFile = tempDir.childFile('test.pid');
+ await _flutter.run(pidFile: pidFile);
+ expect(pidFile.existsSync(), isTrue);
+ });
+ }, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
}
diff --git a/packages/flutter_tools/test/integration.shard/hot_reload_test.dart b/packages/flutter_tools/test/integration.shard/hot_reload_test.dart
index 2d7d3cd..a651294 100644
--- a/packages/flutter_tools/test/integration.shard/hot_reload_test.dart
+++ b/packages/flutter_tools/test/integration.shard/hot_reload_test.dart
@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Integration tests which invoke flutter instead of unit testing the code
+// will not produce meaningful coverage information - we can measure coverage
+// from the isolate running the test, but not from the isolate started via
+// the command line process.
+@Tags(<String>['no_coverage'])
import 'dart:async';
import 'package:file/file.dart';
@@ -15,137 +20,139 @@
import 'test_utils.dart';
void main() {
- Directory tempDir;
- final HotReloadProject _project = HotReloadProject();
- FlutterRunTestDriver _flutter;
+ group('hot reload tests', () {
+ Directory tempDir;
+ final HotReloadProject _project = HotReloadProject();
+ FlutterRunTestDriver _flutter;
- setUp(() async {
- tempDir = createResolvedTempDirectorySync('hot_reload_test.');
- await _project.setUpIn(tempDir);
- _flutter = FlutterRunTestDriver(tempDir);
- });
+ setUp(() async {
+ tempDir = createResolvedTempDirectorySync('hot_reload_test.');
+ await _project.setUpIn(tempDir);
+ _flutter = FlutterRunTestDriver(tempDir);
+ });
- tearDown(() async {
- await _flutter?.stop();
- tryToDelete(tempDir);
- });
+ tearDown(() async {
+ await _flutter?.stop();
+ tryToDelete(tempDir);
+ });
- test('hot reload works without error', () async {
- await _flutter.run();
- await _flutter.hotReload();
- });
-
- test('newly added code executes during hot reload', () async {
- await _flutter.run();
- _project.uncommentHotReloadPrint();
- final StringBuffer stdout = StringBuffer();
- final StreamSubscription<String> subscription = _flutter.stdout.listen(stdout.writeln);
- try {
+ test('hot reload works without error', () async {
+ await _flutter.run();
await _flutter.hotReload();
- expect(stdout.toString(), contains('(((((RELOAD WORKED)))))'));
- } finally {
+ });
+
+ test('newly added code executes during hot reload', () async {
+ await _flutter.run();
+ _project.uncommentHotReloadPrint();
+ final StringBuffer stdout = StringBuffer();
+ final StreamSubscription<String> subscription = _flutter.stdout.listen(stdout.writeln);
+ try {
+ await _flutter.hotReload();
+ expect(stdout.toString(), contains('(((((RELOAD WORKED)))))'));
+ } finally {
+ await subscription.cancel();
+ }
+ });
+
+ test('hot restart works without error', () async {
+ await _flutter.run();
+ await _flutter.hotRestart();
+ });
+
+ test('breakpoints are hit after hot reload', () async {
+ Isolate isolate;
+ await _flutter.run(withDebugger: true, startPaused: true);
+ final Completer<void> sawTick1 = Completer<void>();
+ final Completer<void> sawTick3 = Completer<void>();
+ final Completer<void> sawDebuggerPausedMessage = Completer<void>();
+ final StreamSubscription<String> subscription = _flutter.stdout.listen(
+ (String line) {
+ if (line.contains('((((TICK 1))))')) {
+ expect(sawTick1.isCompleted, isFalse);
+ sawTick1.complete();
+ }
+ if (line.contains('((((TICK 3))))')) {
+ expect(sawTick3.isCompleted, isFalse);
+ sawTick3.complete();
+ }
+ if (line.contains('The application is paused in the debugger on a breakpoint.')) {
+ expect(sawDebuggerPausedMessage.isCompleted, isFalse);
+ sawDebuggerPausedMessage.complete();
+ }
+ },
+ );
+ await _flutter.resume(); // we start paused so we can set up our TICK 1 listener before the app starts
+ unawaited(sawTick1.future.timeout(
+ const Duration(seconds: 5),
+ onTimeout: () { print('The test app is taking longer than expected to print its synchronization line...'); },
+ ));
+ await sawTick1.future; // after this, app is in steady state
+ await _flutter.addBreakpoint(
+ _project.scheduledBreakpointUri,
+ _project.scheduledBreakpointLine,
+ );
+ await _flutter.hotReload(); // reload triggers code which eventually hits the breakpoint
+ isolate = await _flutter.waitForPause();
+ expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
+ await _flutter.resume();
+ await _flutter.addBreakpoint(
+ _project.buildBreakpointUri,
+ _project.buildBreakpointLine,
+ );
+ bool reloaded = false;
+ final Future<void> reloadFuture = _flutter.hotReload().then((void value) { reloaded = true; });
+ await sawTick3.future; // this should happen before it pauses
+ isolate = await _flutter.waitForPause();
+ expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
+ await sawDebuggerPausedMessage.future;
+ expect(reloaded, isFalse);
+ await _flutter.resume();
+ await reloadFuture;
+ expect(reloaded, isTrue);
+ reloaded = false;
await subscription.cancel();
- }
- });
+ });
- test('hot restart works without error', () async {
- await _flutter.run();
- await _flutter.hotRestart();
- });
-
- test('breakpoints are hit after hot reload', () async {
- Isolate isolate;
- await _flutter.run(withDebugger: true, startPaused: true);
- final Completer<void> sawTick1 = Completer<void>();
- final Completer<void> sawTick3 = Completer<void>();
- final Completer<void> sawDebuggerPausedMessage = Completer<void>();
- final StreamSubscription<String> subscription = _flutter.stdout.listen(
- (String line) {
- if (line.contains('((((TICK 1))))')) {
- expect(sawTick1.isCompleted, isFalse);
- sawTick1.complete();
- }
- if (line.contains('((((TICK 3))))')) {
- expect(sawTick3.isCompleted, isFalse);
- sawTick3.complete();
- }
- if (line.contains('The application is paused in the debugger on a breakpoint.')) {
- expect(sawDebuggerPausedMessage.isCompleted, isFalse);
- sawDebuggerPausedMessage.complete();
- }
- },
- );
- await _flutter.resume(); // we start paused so we can set up our TICK 1 listener before the app starts
- unawaited(sawTick1.future.timeout(
- const Duration(seconds: 5),
- onTimeout: () { print('The test app is taking longer than expected to print its synchronization line...'); },
- ));
- await sawTick1.future; // after this, app is in steady state
- await _flutter.addBreakpoint(
- _project.scheduledBreakpointUri,
- _project.scheduledBreakpointLine,
- );
- await _flutter.hotReload(); // reload triggers code which eventually hits the breakpoint
- isolate = await _flutter.waitForPause();
- expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
- await _flutter.resume();
- await _flutter.addBreakpoint(
- _project.buildBreakpointUri,
- _project.buildBreakpointLine,
- );
- bool reloaded = false;
- final Future<void> reloadFuture = _flutter.hotReload().then((void value) { reloaded = true; });
- await sawTick3.future; // this should happen before it pauses
- isolate = await _flutter.waitForPause();
- expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
- await sawDebuggerPausedMessage.future;
- expect(reloaded, isFalse);
- await _flutter.resume();
- await reloadFuture;
- expect(reloaded, isTrue);
- reloaded = false;
- await subscription.cancel();
- });
-
- test('hot reload doesn\'t reassemble if paused', () async {
- await _flutter.run(withDebugger: true);
- final Completer<void> sawTick2 = Completer<void>();
- final Completer<void> sawTick3 = Completer<void>();
- final Completer<void> sawDebuggerPausedMessage1 = Completer<void>();
- final Completer<void> sawDebuggerPausedMessage2 = Completer<void>();
- final StreamSubscription<String> subscription = _flutter.stdout.listen(
- (String line) {
- if (line.contains('((((TICK 2))))')) {
- expect(sawTick2.isCompleted, isFalse);
- sawTick2.complete();
- }
- if (line.contains('The application is paused in the debugger on a breakpoint.')) {
- expect(sawDebuggerPausedMessage1.isCompleted, isFalse);
- sawDebuggerPausedMessage1.complete();
- }
- if (line.contains('The application is paused in the debugger on a breakpoint; interface might not update.')) {
- expect(sawDebuggerPausedMessage2.isCompleted, isFalse);
- sawDebuggerPausedMessage2.complete();
- }
- },
- );
- await _flutter.addBreakpoint(
- _project.buildBreakpointUri,
- _project.buildBreakpointLine,
- );
- bool reloaded = false;
- final Future<void> reloadFuture = _flutter.hotReload().then((void value) { reloaded = true; });
- await sawTick2.future; // this should happen before it pauses
- final Isolate isolate = await _flutter.waitForPause();
- expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
- expect(reloaded, isFalse);
- await sawDebuggerPausedMessage1.future; // this is the one where it say "uh, you broke into the debugger while reloading"
- await reloadFuture; // this is the one where it times out because you're in the debugger
- expect(reloaded, isTrue);
- await _flutter.hotReload(); // now we're already paused
- expect(sawTick3.isCompleted, isFalse);
- await sawDebuggerPausedMessage2.future; // so we just get told that nothing is going to happen
- await _flutter.resume();
- await subscription.cancel();
- });
+ test('hot reload doesn\'t reassemble if paused', () async {
+ await _flutter.run(withDebugger: true);
+ final Completer<void> sawTick2 = Completer<void>();
+ final Completer<void> sawTick3 = Completer<void>();
+ final Completer<void> sawDebuggerPausedMessage1 = Completer<void>();
+ final Completer<void> sawDebuggerPausedMessage2 = Completer<void>();
+ final StreamSubscription<String> subscription = _flutter.stdout.listen(
+ (String line) {
+ if (line.contains('((((TICK 2))))')) {
+ expect(sawTick2.isCompleted, isFalse);
+ sawTick2.complete();
+ }
+ if (line.contains('The application is paused in the debugger on a breakpoint.')) {
+ expect(sawDebuggerPausedMessage1.isCompleted, isFalse);
+ sawDebuggerPausedMessage1.complete();
+ }
+ if (line.contains('The application is paused in the debugger on a breakpoint; interface might not update.')) {
+ expect(sawDebuggerPausedMessage2.isCompleted, isFalse);
+ sawDebuggerPausedMessage2.complete();
+ }
+ },
+ );
+ await _flutter.addBreakpoint(
+ _project.buildBreakpointUri,
+ _project.buildBreakpointLine,
+ );
+ bool reloaded = false;
+ final Future<void> reloadFuture = _flutter.hotReload().then((void value) { reloaded = true; });
+ await sawTick2.future; // this should happen before it pauses
+ final Isolate isolate = await _flutter.waitForPause();
+ expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
+ expect(reloaded, isFalse);
+ await sawDebuggerPausedMessage1.future; // this is the one where it say "uh, you broke into the debugger while reloading"
+ await reloadFuture; // this is the one where it times out because you're in the debugger
+ expect(reloaded, isTrue);
+ await _flutter.hotReload(); // now we're already paused
+ expect(sawTick3.isCompleted, isFalse);
+ await sawDebuggerPausedMessage2.future; // so we just get told that nothing is going to happen
+ await _flutter.resume();
+ await subscription.cancel();
+ });
+ }, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
}
diff --git a/packages/flutter_tools/test/integration.shard/lifetime_test.dart b/packages/flutter_tools/test/integration.shard/lifetime_test.dart
index 1ff3152..9e5284a 100644
--- a/packages/flutter_tools/test/integration.shard/lifetime_test.dart
+++ b/packages/flutter_tools/test/integration.shard/lifetime_test.dart
@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Integration tests which invoke flutter instead of unit testing the code
+// will not produce meaningful coverage information - we can measure coverage
+// from the isolate running the test, but not from the isolate started via
+// the command line process.
+@Tags(<String>['no_coverage'])
import 'dart:async';
import 'package:file/file.dart';
@@ -18,30 +23,32 @@
const Duration requiredLifespan = Duration(seconds: 5);
void main() {
- final BasicProject _project = BasicProject();
- FlutterRunTestDriver _flutter;
- Directory tempDir;
+ group('flutter run', () {
+ final BasicProject _project = BasicProject();
+ FlutterRunTestDriver _flutter;
+ Directory tempDir;
- setUp(() async {
- tempDir = createResolvedTempDirectorySync('lifetime_test.');
- await _project.setUpIn(tempDir);
- _flutter = FlutterRunTestDriver(tempDir);
- });
+ setUp(() async {
+ tempDir = createResolvedTempDirectorySync('lifetime_test.');
+ await _project.setUpIn(tempDir);
+ _flutter = FlutterRunTestDriver(tempDir);
+ });
- tearDown(() async {
- await _flutter.stop();
- tryToDelete(tempDir);
- });
+ tearDown(() async {
+ await _flutter.stop();
+ tryToDelete(tempDir);
+ });
- test('flutter run does not terminate when a debugger is attached', () async {
- await _flutter.run(withDebugger: true);
- await Future<void>.delayed(requiredLifespan);
- expect(_flutter.hasExited, equals(false));
- });
+ test('does not terminate when a debugger is attached', () async {
+ await _flutter.run(withDebugger: true);
+ await Future<void>.delayed(requiredLifespan);
+ expect(_flutter.hasExited, equals(false));
+ });
- test('fluter run does not terminate when a debugger is attached and pause-on-exceptions', () async {
- await _flutter.run(withDebugger: true, pauseOnExceptions: true);
- await Future<void>.delayed(requiredLifespan);
- expect(_flutter.hasExited, equals(false));
- });
+ test('does not terminate when a debugger is attached and pause-on-exceptions', () async {
+ await _flutter.run(withDebugger: true, pauseOnExceptions: true);
+ await Future<void>.delayed(requiredLifespan);
+ expect(_flutter.hasExited, equals(false));
+ });
+ }, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
}
diff --git a/packages/flutter_tools/test/src/common.dart b/packages/flutter_tools/test/src/common.dart
index 00de957..7741daf 100644
--- a/packages/flutter_tools/test/src/common.dart
+++ b/packages/flutter_tools/test/src/common.dart
@@ -127,6 +127,13 @@
return projectPath;
}
+/// Test case timeout for tests involving remote calls to `pub get` or similar.
+const Timeout allowForRemotePubInvocation = Timeout.factor(10.0);
+
+/// Test case timeout for tests involving creating a Flutter project with
+/// `--no-pub`. Use [allowForRemotePubInvocation] when creation involves `pub`.
+const Timeout allowForCreateFlutterProject = Timeout.factor(3.0);
+
Future<void> expectToolExitLater(Future<dynamic> future, Matcher messageMatcher) async {
try {
await future;
diff --git a/packages/flutter_tools/test/src/context.dart b/packages/flutter_tools/test/src/context.dart
index 7f1fdff..57e4465 100644
--- a/packages/flutter_tools/test/src/context.dart
+++ b/packages/flutter_tools/test/src/context.dart
@@ -48,6 +48,7 @@
void testUsingContext(
String description,
dynamic testMethod(), {
+ Timeout timeout,
Map<Type, Generator> overrides = const <Type, Generator>{},
bool initializeFlutterRoot = true,
String testOn,
@@ -136,7 +137,8 @@
},
);
});
- }, testOn: testOn, skip: skip);
+ }, timeout: timeout ?? const Timeout(Duration(seconds: 60)),
+ testOn: testOn, skip: skip);
}
void _printBufferedErrors(AppContext testContext) {