diff --git a/.github/actions/pr_notifier/pr_notifier.py b/.github/actions/pr_notifier/pr_notifier.py index 556ab11026..05f5adce85 100644 --- a/.github/actions/pr_notifier/pr_notifier.py +++ b/.github/actions/pr_notifier/pr_notifier.py @@ -31,6 +31,7 @@ 'snowp': 'U93KTPQP6', } + def get_slo_hours(): # on Monday, allow for 24h + 48h if datetime.date.today().weekday() == 0: @@ -58,8 +59,7 @@ def pr_message(pr_age, pr_url, pr_title, delta_days, delta_hours): # Adds reminder lines to the appropriate assignee to review the assigned PRs # Returns true if one of the assignees is in the primary_assignee_map, false otherwise. -def add_reminders( - assignees, assignees_and_prs, message, primary_assignee_map): +def add_reminders(assignees, assignees_and_prs, message, primary_assignee_map): has_primary_assignee = False for assignee_info in assignees: assignee = assignee_info.login @@ -92,7 +92,7 @@ def track_prs(): if pr_info.draft: continue # envoy-mobile currently doesn't triage unassigned PRs. - if not(pr_info.assignees): + if not (pr_info.assignees): continue # Update the time based on the time zone delta from github's diff --git a/.github/lyft_maintainers.yml b/.github/lyft_maintainers.yml index 59a99f20cd..b65f00ca75 100644 --- a/.github/lyft_maintainers.yml +++ b/.github/lyft_maintainers.yml @@ -1,5 +1,4 @@ -current: Augustyniak +current: jpsim maintainers: - Augustyniak - - snowp - jpsim diff --git a/.github/workflows/android_tests.yml b/.github/workflows/android_tests.yml index 61bf5a8d21..d890e4e1c8 100644 --- a/.github/workflows/android_tests.yml +++ b/.github/workflows/android_tests.yml @@ -22,10 +22,10 @@ jobs: run: | if git rev-parse --abbrev-ref HEAD | grep -q ^main$ || git diff --name-only origin/main | grep -qe common/ -e java/ -e kotlin/ -e bazel/ -e ^\.bazelrc$ -e ^envoy$ -e ^WORKSPACE$ -e ^.github/workflows/android_tests.yml$ ; then echo "Tests will run." - echo "::set-output name=run_tests::true" + echo "run_tests=true" >> $GITHUB_OUTPUT else echo "Skipping tests." - echo "::set-output name=run_tests::false" + echo "run_tests=false" >> $GITHUB_OUTPUT fi - name: 'Java setup' if: steps.check_context.outputs.run_tests == 'true' @@ -61,10 +61,10 @@ jobs: run: | if git rev-parse --abbrev-ref HEAD | grep -q ^main$ || git diff --name-only origin/main | grep -qe common/ -e java/ -e kotlin/ -e bazel/ -e ^\.bazelrc$ -e ^envoy$ -e ^WORKSPACE$ -e ^.github/workflows/android_tests.yml$ ; then echo "Tests will run." - echo "::set-output name=run_tests::true" + echo "run_tests=true" >> $GITHUB_OUTPUT else echo "Skipping tests." - echo "::set-output name=run_tests::false" + echo "run_tests=false" >> $GITHUB_OUTPUT fi - name: 'Java setup' if: steps.check_context.outputs.run_tests == 'true' @@ -110,10 +110,10 @@ jobs: run: | if git rev-parse --abbrev-ref HEAD | grep -q ^main$ || git diff --name-only origin/main | grep -qe common/ -e java/ -e kotlin/ -e bazel/ -e ^\.bazelrc$ -e ^envoy$ -e ^WORKSPACE$ -e ^.github/workflows/android_tests.yml$ ; then echo "Tests will run." - echo "::set-output name=run_tests::true" + echo "run_tests=true" >> $GITHUB_OUTPUT else echo "Skipping tests." - echo "::set-output name=run_tests::false" + echo "run_tests=false" >> $GITHUB_OUTPUT fi - name: 'Java setup' if: steps.check_context.outputs.run_tests == 'true' diff --git a/.github/workflows/asan.yml b/.github/workflows/asan.yml index cef3a6fa2d..ace378370b 100644 --- a/.github/workflows/asan.yml +++ b/.github/workflows/asan.yml @@ -27,10 +27,10 @@ jobs: run: | if git rev-parse --abbrev-ref HEAD | grep -q ^main$ || git diff --name-only origin/main | grep -qe common/ -e bazel/ -e ^\.bazelrc$ -e ^envoy$ -e ^WORKSPACE$ -e ^.github/workflows/asan.yml$ ; then echo "Tests will run." - echo "::set-output name=run_tests::true" + echo "run_tests=true" >> $GITHUB_OUTPUT else echo "Skipping tests." - echo "::set-output name=run_tests::false" + echo "run_tests=false" >> $GITHUB_OUTPUT fi - uses: actions/setup-java@v1 if: steps.check-cache.outputs.cache-hit != 'true' diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 94a957a1f3..00828f7c0e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -27,10 +27,10 @@ jobs: run: | if git rev-parse --abbrev-ref HEAD | grep -q ^main$ || git diff --name-only origin/main | grep -qe common/ -e ^.github/workflows/coverage.yml ; then echo "Coverage will run." - echo "::set-output name=run_coverage::true" + echo "run_coverage=true" >> $GITHUB_OUTPUT else echo "Skipping coverage." - echo "::set-output name=run_coverage::false" + echo "run_coverage=false" >> $GITHUB_OUTPUT fi - name: 'Run coverage' if: steps.check_context.outputs.run_coverage == 'true' diff --git a/.github/workflows/ios_build.yml b/.github/workflows/ios_build.yml index b3c48a3706..d8c4326dda 100644 --- a/.github/workflows/ios_build.yml +++ b/.github/workflows/ios_build.yml @@ -31,7 +31,7 @@ jobs: name: swift_helloworld needs: iosbuild runs-on: macos-12 - timeout-minutes: 25 + timeout-minutes: 35 steps: - uses: actions/checkout@v1 with: @@ -136,7 +136,7 @@ jobs: name: swift_async_await needs: iosbuild runs-on: macos-12 - timeout-minutes: 25 + timeout-minutes: 35 steps: - uses: actions/checkout@v1 with: diff --git a/.github/workflows/ios_tests.yml b/.github/workflows/ios_tests.yml index e607d9f3ce..725a0917e2 100644 --- a/.github/workflows/ios_tests.yml +++ b/.github/workflows/ios_tests.yml @@ -20,10 +20,10 @@ jobs: run: | if git rev-parse --abbrev-ref HEAD | grep -q ^main$ || git diff --name-only origin/main | grep -qe common/ -e objective-c/ -e swift/ -e bazel/ -e ^\.bazelrc$ -e ^envoy$ -e ^WORKSPACE$ -e ^.github/workflows/ios_tests.yml$ ; then echo "Tests will run." - echo "::set-output name=run_tests::true" + echo "run_tests=true" >> $GITHUB_OUTPUT else echo "Skipping tests." - echo "::set-output name=run_tests::false" + echo "run_tests=false" >> $GITHUB_OUTPUT fi - name: 'Install dependencies' run: ./ci/mac_ci_setup.sh @@ -53,10 +53,10 @@ jobs: run: | if git rev-parse --abbrev-ref HEAD | grep -q ^main$ || git diff --name-only origin/main | grep -qe common/ -e objective-c/ -e swift/ -e bazel/ -e ^\.bazelrc$ -e ^envoy$ -e ^WORKSPACE$ -e ^.github/workflows/ios_tests.yml$ ; then echo "Tests will run." - echo "::set-output name=run_tests::true" + echo "run_tests=true" >> $GITHUB_OUTPUT else echo "Skipping tests." - echo "::set-output name=run_tests::false" + echo "run_tests=false" >> $GITHUB_OUTPUT fi - name: 'Install dependencies' run: ./ci/mac_ci_setup.sh diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index f149421a87..2d78925ff0 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -24,10 +24,10 @@ jobs: run: | if git rev-parse --abbrev-ref HEAD | grep -q ^main$ || git diff --name-only origin/main | grep -qe common/ -e cc/ -e python/ -e bazel/ -e ^\.bazelrc$ -e ^envoy$ -e ^WORKSPACE$ -e ^.github/workflows/python_tests.yml$ ; then echo "Tests will run." - echo "::set-output name=run_tests::true" + echo "run_tests=true" >> $GITHUB_OUTPUT else echo "Skipping tests." - echo "::set-output name=run_tests::false" + echo "run_tests=false" >> $GITHUB_OUTPUT fi - name: 'Run tests' if: steps.check_context.outputs.run_tests == 'true' diff --git a/.github/workflows/submodule_update.yml b/.github/workflows/submodule_update.yml index b218a40e24..821ea04c9f 100644 --- a/.github/workflows/submodule_update.yml +++ b/.github/workflows/submodule_update.yml @@ -22,7 +22,7 @@ jobs: run: | if ! git diff-index --quiet HEAD --; then echo "Detected changes..." - echo "::set-output name=dirty::true" + echo "dirty=true" >> $GITHUB_OUTPUT fi - name: Get current support maintainer if: steps.state.outputs.dirty == 'true' @@ -31,7 +31,7 @@ jobs: maintainers_file=".github/lyft_maintainers.yml" first_line="$(head -n 1 "$maintainers_file")" current=${first_line#"current: "} - echo "::set-output name=maintainer::$current" + echo "maintainer=$current" >> $GITHUB_OUTPUT - name: Create PR if: steps.state.outputs.dirty == 'true' uses: peter-evans/create-pull-request@923ad837f191474af6b1721408744feb989a4c27 diff --git a/.github/workflows/tsan.yml b/.github/workflows/tsan.yml index da6057db98..f0694da77f 100644 --- a/.github/workflows/tsan.yml +++ b/.github/workflows/tsan.yml @@ -27,10 +27,10 @@ jobs: run: | if git rev-parse --abbrev-ref HEAD | grep -q ^main$ || git diff --name-only origin/main | grep -qe common/ -e bazel/ -e ^\.bazelrc$ -e ^envoy$ -e ^WORKSPACE$ -e ^.github/workflows/tsan.yml$ ; then echo "Tests will run." - echo "::set-output name=run_tests::true" + echo "run_tests=true" >> $GITHUB_OUTPUT else echo "Skipping tests." - echo "::set-output name=run_tests::false" + echo "run_tests=false" >> $GITHUB_OUTPUT fi - uses: actions/setup-java@v1 if: steps.check-cache.outputs.cache-hit != 'true' diff --git a/WORKSPACE b/WORKSPACE index 27ea2d9456..9e42491d37 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -66,6 +66,9 @@ python_configure(name = "local_config_python", python_version = "3") load("//bazel:python.bzl", "declare_python_abi") declare_python_abi(name = "python_abi", python_version = "3") +load("@mobile_pip3//:requirements.bzl", pip_dependencies = "install_deps") +pip_dependencies() + load("//bazel:android_configure.bzl", "android_configure") android_configure( name = "local_config_android", diff --git a/bazel/boringssl.patch b/bazel/boringssl.patch deleted file mode 100644 index 69a854ad3c..0000000000 --- a/bazel/boringssl.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- src/include/openssl/base.h -+++ src/include/openssl/base.h -@@ -258,7 +258,7 @@ extern "C" { - // with the old gnu89 model: - // https://stackoverflow.com/questions/216510/extern-inline - #if defined(__cplusplus) --#define OPENSSL_INLINE inline -+#define OPENSSL_INLINE static inline - #else - // Add OPENSSL_UNUSED so that, should an inline function be emitted via macro - // (e.g. a |STACK_OF(T)| implementation) in a source file without tripping diff --git a/bazel/envoy_mobile_dependencies.bzl b/bazel/envoy_mobile_dependencies.bzl index fc5dd6b36b..d4c98868c3 100644 --- a/bazel/envoy_mobile_dependencies.bzl +++ b/bazel/envoy_mobile_dependencies.bzl @@ -6,7 +6,7 @@ load("@rules_detekt//detekt:dependencies.bzl", "rules_detekt_dependencies") load("@io_bazel_rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories") load("@rules_proto_grpc//:repositories.bzl", "rules_proto_grpc_repos", "rules_proto_grpc_toolchains") load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") -load("@rules_python//python:pip.bzl", "pip_install") +load("@rules_python//python:pip.bzl", "pip_parse") load("@robolectric//bazel:robolectric.bzl", "robolectric_repositories") load("@rules_java//java:repositories.bzl", "rules_java_dependencies") @@ -110,7 +110,8 @@ def python_dependencies(): # pip_install( # requirements = ":dev_requirements.txt", # ) - pip_install( - requirements = "//third_party/python:requirements.txt", + pip_parse( + name = "mobile_pip3", + requirements_lock = "//third_party/python:requirements.txt", timeout = 1000, ) diff --git a/bazel/envoy_mobile_repositories.bzl b/bazel/envoy_mobile_repositories.bzl index eda9364e75..4d0890526d 100644 --- a/bazel/envoy_mobile_repositories.bzl +++ b/bazel/envoy_mobile_repositories.bzl @@ -55,7 +55,6 @@ def upstream_envoy_overrides(): # Remove this once https://boringssl-review.googlesource.com/c/boringssl/+/37804 is in master-with-bazel http_archive( name = "boringssl", - patches = ["@envoy_mobile//bazel:boringssl.patch"], sha256 = "579cb415458e9f3642da0a39a72f79fdfe6dc9c1713b3a823f1e276681b9703e", strip_prefix = "boringssl-648cbaf033401b7fe7acdce02f275b06a88aab5c", urls = ["https://github.com/google/boringssl/archive/648cbaf033401b7fe7acdce02f275b06a88aab5c.tar.gz"], diff --git a/bazelw b/bazelw index 9347022cc9..6a67bcef3f 100755 --- a/bazelw +++ b/bazelw @@ -10,7 +10,8 @@ else readonly bazel_os="linux" fi -readonly raw_arch="$(uname -m)" +raw_arch="$(uname -m)" +readonly raw_arch if [[ "$raw_arch" == "aarch64" || "$raw_arch" == "arm64" ]]; then readonly bazel_arch="arm64" else diff --git a/ci/linux_ci_setup.sh b/ci/linux_ci_setup.sh index 8712662569..cb93cac12a 100755 --- a/ci/linux_ci_setup.sh +++ b/ci/linux_ci_setup.sh @@ -24,6 +24,8 @@ echo "y" | $SDKMANAGER --install "ndk;21.4.7075529" $SDKMANAGER --install "platforms;android-30" $SDKMANAGER --install "build-tools;30.0.2" -echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV -echo "ANDROID_SDK_ROOT=$ANDROID_HOME" >> $GITHUB_ENV -echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/21.4.7075529" >> $GITHUB_ENV +{ + echo "ANDROID_HOME=${ANDROID_HOME}" + echo "ANDROID_SDK_ROOT=${ANDROID_HOME}" + echo "ANDROID_NDK_HOME=${ANDROID_HOME}/ndk/21.4.7075529" +} >> "$GITHUB_ENV" diff --git a/ci/mac_ci_setup.sh b/ci/mac_ci_setup.sh index a0d908fc21..953a08d24d 100755 --- a/ci/mac_ci_setup.sh +++ b/ci/mac_ci_setup.sh @@ -54,9 +54,9 @@ if [[ "${1:-}" == "--android" ]]; then SDKMANAGER="${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager" $SDKMANAGER --uninstall "ndk-bundle" echo "y" | $SDKMANAGER "ndk;21.4.7075529" - ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 "${ANDROID_SDK_ROOT}/ndk-bundle" + ln -sfn "${ANDROID_SDK_ROOT}/ndk/21.4.7075529" "${ANDROID_SDK_ROOT}/ndk-bundle" # Download and set up build-tools 30.0.3, 31.0.0 is missing dx.jar. $SDKMANAGER --install "build-tools;30.0.3" - echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/21.4.7075529" >> $GITHUB_ENV + echo "ANDROID_NDK_HOME=${ANDROID_HOME}/ndk/21.4.7075529" >> "$GITHUB_ENV" fi diff --git a/ci/mac_start_emulator.sh b/ci/mac_start_emulator.sh index c4d85a4a0c..ea9f633e13 100755 --- a/ci/mac_start_emulator.sh +++ b/ci/mac_start_emulator.sh @@ -2,7 +2,11 @@ set -e -echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-29;google_apis;x86_64' --channel=3 -echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n test_android_emulator -k 'system-images;android-29;google_apis;x86_64' --force -ls $ANDROID_HOME/tools/bin/ -nohup $ANDROID_HOME/emulator/emulator -partition-size 1024 -avd test_android_emulator -no-snapshot > /dev/null 2>&1 & $ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 1; done; input keyevent 82' +echo "y" | "${ANDROID_HOME}/tools/bin/sdkmanager" --install 'system-images;android-29;google_apis;x86_64' --channel=3 +echo "no" | "${ANDROID_HOME}/tools/bin/avdmanager" create avd -n test_android_emulator -k 'system-images;android-29;google_apis;x86_64' --force +ls "${ANDROID_HOME}/tools/bin/" + +nohup "${ANDROID_HOME}/emulator/emulator" -partition-size 1024 -avd test_android_emulator -no-snapshot > /dev/null 2>&1 & { + # shellcheck disable=SC2016 + "${ANDROID_HOME}/platform-tools/adb" wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\''\r'\'') ]]; do sleep 1; done; input keyevent 82' +} diff --git a/ci/sonatype_nexus_upload.py b/ci/sonatype_nexus_upload.py index d0196dd8a6..1a37c090a2 100755 --- a/ci/sonatype_nexus_upload.py +++ b/ci/sonatype_nexus_upload.py @@ -16,14 +16,15 @@ _USER_CREDS = os.environ.get("READWRITE_USER", "") _KEY_CREDS = os.environ.get("READWRITE_API_KEY", "") -BASE64_ENCODED_CREDENTIALS = base64.b64encode("{}:{}".format(_USER_CREDS, _KEY_CREDS).encode()).decode() +BASE64_ENCODED_CREDENTIALS = base64.b64encode("{}:{}".format(_USER_CREDS, + _KEY_CREDS).encode()).decode() _ARTIFACT_HOST_URL = "https://oss.sonatype.org/service/local/staging" _GROUP_ID = "io.envoyproxy.envoymobile" _ARTIFACT_ID = "envoy" -_LOCAL_INSTALL_PATH = os.path.expanduser("~/.m2/repository/{directory}/envoy".format( - directory=_GROUP_ID.replace(".", "/"), - artifact_id=_ARTIFACT_ID)) +_LOCAL_INSTALL_PATH = os.path.expanduser( + "~/.m2/repository/{directory}/envoy".format( + directory=_GROUP_ID.replace(".", "/"), artifact_id=_ARTIFACT_ID)) def _resolve_name(file): @@ -63,11 +64,7 @@ def _install_locally(version, files): for file in files: suffix, file_extension = _resolve_name(file) basename = "{name}-{version}{suffix}.{extension}".format( - name=_ARTIFACT_ID, - version=version, - suffix=suffix, - extension=file_extension - ) + name=_ARTIFACT_ID, version=version, suffix=suffix, extension=file_extension) shutil.copyfile(file, os.path.join(path, basename)) print("{file_name}\n{sha}\n".format(file_name=file, sha=_sha256(file))) @@ -89,17 +86,14 @@ def _urlopen_retried(request, max_retries=500, attempt=1, delay_sec=1): if max_retries > attempt and e.code >= 500: print( "[{retry_attempt}/{max_retries} Retry attempt] Retrying request after {delay}s." - " Received error code {code}" - .format( - retry_attempt=attempt, - max_retries=max_retries, - delay=delay_sec, - code=e.code - )) + " Received error code {code}".format( + retry_attempt=attempt, max_retries=max_retries, delay=delay_sec, code=e.code)) time.sleep(delay_sec) return _urlopen_retried(request, max_retries, attempt + 1) elif max_retries <= attempt: - print("Retry limit reached. Will not continue to retry. Received error code {}".format(e.code)) + print( + "Retry limit reached. Will not continue to retry. Received error code {}".format( + e.code)) raise e else: raise e @@ -108,11 +102,7 @@ def _urlopen_retried(request, max_retries=500, attempt=1, delay_sec=1): def _create_staging_repository(profile_id): try: url = os.path.join(_ARTIFACT_HOST_URL, "profiles/{}/start".format(profile_id)) - data = { - 'data': { - 'description': '' - } - } + data = {'data': {'description': ''}} request = Request(url) request.add_header("Authorization", "Basic {}".format(BASE64_ENCODED_CREDENTIALS)) request.add_header("Content-Type", "application/json") @@ -137,27 +127,19 @@ def _upload_files(staging_id, version, files, ascs, sha256): print("Uploading file {}".format(file)) suffix, file_extension = _resolve_name(file) basename = "{name}-{version}{suffix}.{extension}".format( - name=_ARTIFACT_ID, - version=version, - suffix=suffix, - extension=file_extension - ) + name=_ARTIFACT_ID, version=version, suffix=suffix, extension=file_extension) artifact_url = os.path.join( - _ARTIFACT_HOST_URL, - "deployByRepositoryId/{}".format(staging_id), - _GROUP_ID.replace('.', "/"), - _ARTIFACT_ID, - version, - basename - ) + _ARTIFACT_HOST_URL, "deployByRepositoryId/{}".format(staging_id), + _GROUP_ID.replace('.', "/"), _ARTIFACT_ID, version, basename) try: with open(file, "rb") as f: request = Request(artifact_url, f.read()) request.add_header("Authorization", "Basic {}".format(BASE64_ENCODED_CREDENTIALS)) - request.add_header("Content-Type", "application/x-{extension}".format(extension=file_extension)) + request.add_header( + "Content-Type", "application/x-{extension}".format(extension=file_extension)) request.get_method = lambda: "PUT" _urlopen_retried(request) uploaded_file_count = uploaded_file_count + 1 @@ -175,12 +157,7 @@ def _upload_files(staging_id, version, files, ascs, sha256): def _close_staging_repository(profile_id, staging_id): url = os.path.join(_ARTIFACT_HOST_URL, "profiles/{}/finish".format(profile_id)) - data = { - 'data': { - 'stagedRepositoryId': staging_id, - 'description': '' - } - } + data = {'data': {'stagedRepositoryId': staging_id, 'description': ''}} try: request = Request(url) @@ -196,12 +173,7 @@ def _close_staging_repository(profile_id, staging_id): def _drop_staging_repository(staging_id, message): url = os.path.join(_ARTIFACT_HOST_URL, "bulk/drop") - data = { - 'data': { - 'stagedRepositoryIds': [staging_id], - 'description': message - } - } + data = {'data': {'stagedRepositoryIds': [staging_id], 'description': message}} try: request = Request(url) @@ -217,12 +189,7 @@ def _drop_staging_repository(staging_id, message): def _release_staging_repository(staging_id): url = os.path.join(_ARTIFACT_HOST_URL, "bulk/promote") - data = { - 'data': { - 'stagedRepositoryIds': [staging_id], - 'description': '' - } - } + data = {'data': {'stagedRepositoryIds': [staging_id], 'description': ''}} try: request = Request(url) @@ -258,26 +225,37 @@ def _sha256(file_name): def _build_parser(): parser = argparse.ArgumentParser() - parser.add_argument("--profile_id", required=False, - help=""" + parser.add_argument( + "--profile_id", + required=False, + help=""" The staging profile id of the sonatype repository target. This is the id in the sonatype web ui. The REST api is: curl -u {usr}:{psswrd} -H "Accept: application/json" https://oss.sonatype.org//nexus/service/local/staging/profile_repositories """) - parser.add_argument("--version", default="LOCAL-SNAPSHOT", - help=""" + parser.add_argument( + "--version", + default="LOCAL-SNAPSHOT", + help=""" The version of the artifact to be published. `LOCAL-SNAPSHOT` is defaulted if the version is not set. This version should be consistent with the pom.xml provided. """) - parser.add_argument("--local", nargs='?', const=True, default=False, - help=""" + parser.add_argument( + "--local", + nargs='?', + const=True, + default=False, + help=""" For installing artifacts into local maven. For now, we only support installing to the path `~/.m2/repository/io/envoyproxy/envoymobile/` """) - parser.add_argument("--files", nargs="+", required=True, - help=""" + parser.add_argument( + "--files", + nargs="+", + required=True, + help=""" Files to upload The checklist for Envoy Mobile files are: @@ -286,8 +264,11 @@ def _build_parser(): envoy-sources.jar envoy-javadoc.jar """) - parser.add_argument("--signed_files", nargs="+", required=False, - help=""" + parser.add_argument( + "--signed_files", + nargs="+", + required=False, + help=""" Files to upload. Sonatype requires uploaded artifacts to be gpg signed @@ -320,7 +301,8 @@ def _build_parser(): try: print("Uploading files...") sha256_files = _create_sha256_files(args.files) - uploaded_file_count = _upload_files(staging_id, version, args.files, args.signed_files, sha256_files) + uploaded_file_count = _upload_files( + staging_id, version, args.files, args.signed_files, sha256_files) if uploaded_file_count > 0: print("Uploading files complete!") print("Closing staging repository...") @@ -336,7 +318,9 @@ def _build_parser(): except Exception as e: print(e) - print("Unable to complete file upload. Will attempt to drop staging id: [{}]".format(staging_id)) + print( + "Unable to complete file upload. Will attempt to drop staging id: [{}]".format( + staging_id)) try: _drop_staging_repository(staging_id, "droppng release due to error") sys.exit("Dropping staging id: [{}] successful.".format(staging_id)) diff --git a/ci/test_size_regression.sh b/ci/test_size_regression.sh index 43ea094aae..d5b03618a8 100755 --- a/ci/test_size_regression.sh +++ b/ci/test_size_regression.sh @@ -5,7 +5,7 @@ MAX_SIZE=7300000 # 7.3MB MAX_PERC=2.0 -if [ `uname` == "Darwin" ] +if [ "$(uname)" == "Darwin" ] then SIZE1=$(stat -f "%z" "$1") SIZE2=$(stat -f "%z" "$2") @@ -18,13 +18,13 @@ PERC=$(bc <<< "scale=2; ($SIZE2 - $SIZE1)/$SIZE1 * 100") echo "The new binary is $PERC % different in size compared to main." echo "The new binary is $SIZE2 bytes." -if [ $SIZE2 -gt $MAX_SIZE ] +if [ "$SIZE2" -gt $MAX_SIZE ] then echo "The current size ($SIZE2) is larger than the maximum size ($MAX_SIZE)." exit 1 fi -if [ $(bc <<< "scale=2; $PERC >= $MAX_PERC") -eq 1 ] +if [ "$(bc <<< "scale=2; $PERC >= $MAX_PERC")" -eq 1 ] then echo "The percentage increase ($PERC) is larger then the maximum percentage increase ($MAX_PERC)." exit 1 diff --git a/docs/build.sh b/docs/build.sh index c2e02e8cce..bb3ded52b0 100755 --- a/docs/build.sh +++ b/docs/build.sh @@ -2,6 +2,7 @@ set -e +# shellcheck disable=SC1091 . envoy/tools/shell_utils.sh # We need to set ENVOY_DOCS_VERSION_STRING and ENVOY_DOCS_RELEASE_LEVEL for Sphinx. diff --git a/docs/conf.py b/docs/conf.py index 3e7e11cccd..752efe6b19 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -21,35 +21,35 @@ # https://stackoverflow.com/questions/44761197/how-to-use-substitution-definitions-with-code-blocks class SubstitutionCodeBlock(CodeBlock): - """ + """ Similar to CodeBlock but replaces placeholders with variables. See "substitutions" below. """ - def run(self): - """ + def run(self): + """ Replace placeholders with given variables. """ - app = self.state.document.settings.env.app - new_content = [] - existing_content = self.content - for item in existing_content: - for pair in app.config.substitutions: - original, replacement = pair - item = item.replace(original, replacement) - new_content.append(item) + app = self.state.document.settings.env.app + new_content = [] + existing_content = self.content + for item in existing_content: + for pair in app.config.substitutions: + original, replacement = pair + item = item.replace(original, replacement) + new_content.append(item) - self.content = new_content - return list(CodeBlock.run(self)) + self.content = new_content + return list(CodeBlock.run(self)) def setup(app): - app.add_config_value('release_level', '', 'env') - app.add_config_value('substitutions', [], 'html') - app.add_directive('substitution-code-block', SubstitutionCodeBlock) + app.add_config_value('release_level', '', 'env') + app.add_config_value('substitutions', [], 'html') + app.add_directive('substitution-code-block', SubstitutionCodeBlock) if not os.environ.get('ENVOY_DOCS_RELEASE_LEVEL'): - raise Exception("ENVOY_DOCS_RELEASE_LEVEL env var must be defined") + raise Exception("ENVOY_DOCS_RELEASE_LEVEL env var must be defined") release_level = os.environ['ENVOY_DOCS_RELEASE_LEVEL'] blob_sha = os.environ['ENVOY_BLOB_SHA'] @@ -101,7 +101,7 @@ def setup(app): # built documents. if not os.environ.get('ENVOY_DOCS_VERSION_STRING'): - raise Exception("ENVOY_DOCS_VERSION_STRING env var must be defined") + raise Exception("ENVOY_DOCS_VERSION_STRING env var must be defined") # The short X.Y version. version = os.environ['ENVOY_DOCS_VERSION_STRING'] diff --git a/docs/publish.sh b/docs/publish.sh index 7eb52fb66f..5212617416 100755 --- a/docs/publish.sh +++ b/docs/publish.sh @@ -11,7 +11,7 @@ set -e DOCS_DIR=generated/docs CHECKOUT_DIR=../envoy-mobile-docs -BUILD_SHA=`git rev-parse HEAD` +BUILD_SHA="$(git rev-parse HEAD)" if [ -n "$CIRCLE_TAG" ] then diff --git a/docs/root/api/starting_envoy.rst b/docs/root/api/starting_envoy.rst index 0fad51fe68..c72e45e230 100644 --- a/docs/root/api/starting_envoy.rst +++ b/docs/root/api/starting_envoy.rst @@ -116,36 +116,6 @@ The configuration is expected as a JSON list. // Swift builder.addDNSPreresolveHostnames("[{\"address\": \"foo.com", \"port_value\": 443}]") -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -``addDNSFallbackNameservers`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. attention:: - - This API is only available for Kotlin. - -Add a list of IP addresses to use as fallback DNS name servers. -See `the Envoy docs `__ -for further information. - - // Kotlin - builder.addDNSFallbackNameservers(listOf("8.8.8.8")) - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -``enableDNSFilterUnroutableFamilies`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. attention:: - - This API is only available for Kotlin. - -Specify whether to filter unroutable IP families during DNS resolution or not. -See `the Envoy docs `__ -for further information. - - // Kotlin - builder.enableDNSFilterUnroutableFamilies(true) - ~~~~~~~~~~~~~~~ ``addLogLevel`` ~~~~~~~~~~~~~~~ diff --git a/docs/root/intro/version_history.rst b/docs/root/intro/version_history.rst index f239ad3dd6..0f882ad635 100644 --- a/docs/root/intro/version_history.rst +++ b/docs/root/intro/version_history.rst @@ -9,6 +9,7 @@ Breaking changes: - ios/android: remove ``addH2RawDomains`` method. (:issue: `#2590 <2590>`) - build: building on macOS now requires Xcode 14.0. (:issue:`#2544 <2544>`) - iOS: remove experimental option to force all connections to use IPv6. +- kotlin: always use ``getaddrinfo`` DNS resolver. Remove ``addDNSFallbackNameservers``, ``enableDNSFilterUnroutableFamilies``, and ``enableDNSUseSystemResolver`` methods from the Kotlin engine builder. (:issue:`#2618 <2618>`) Bugfixes: @@ -23,6 +24,7 @@ Features: - kotlin: add a ``enableSkipDNSLookupForProxiedRequests(true)`` knob for controlling whether Envoy waits on DNS response in the dynamic forward proxy filter for proxied requests. (:issue:`#2602 <2602>`) - api: Add various methods to C++ EngineBuilder to bring it to parity with the Java and Obj-C builders. (:issue:`#2498 <2498>`) - api: Add support for String Accessors to the C++ EngineBuilder. (:issue:`#2498 <2498>`) +- api: Add support for Native Filters and Platform Filters to the C++ EngineBuilder. (:issue:`#2498 <2498>`) - api: added upstream protocol to final stream intel. (:issue:`#2613 <2613>`) 0.5.0 (September 2, 2022) diff --git a/envoy b/envoy index 369de3e09c..d57e496f61 160000 --- a/envoy +++ b/envoy @@ -1 +1 @@ -Subproject commit 369de3e09c65791148c343e6f125bc3b2169dd75 +Subproject commit d57e496f617b20327eaabb6fe002f3935ecf5ea8 diff --git a/envoy_build_config/BUILD b/envoy_build_config/BUILD index 8c9337320f..5dd9dacadd 100644 --- a/envoy_build_config/BUILD +++ b/envoy_build_config/BUILD @@ -26,6 +26,7 @@ envoy_cc_library( "@envoy//source/extensions/filters/http/router:config", "@envoy//source/extensions/filters/network/http_connection_manager:config", "@envoy//source/extensions/http/header_formatters/preserve_case:config", + "@envoy//source/extensions/network/dns_resolver/getaddrinfo:config", "@envoy//source/extensions/stat_sinks/metrics_service:config", "@envoy//source/extensions/stat_sinks/statsd:config", "@envoy//source/extensions/transport_sockets/http_11_proxy:upstream_config", diff --git a/envoy_build_config/extension_registry.cc b/envoy_build_config/extension_registry.cc index 6110ba48a5..8e24d20547 100644 --- a/envoy_build_config/extension_registry.cc +++ b/envoy_build_config/extension_registry.cc @@ -15,6 +15,7 @@ #include "source/extensions/filters/network/http_connection_manager/config.h" #include "source/extensions/http/header_formatters/preserve_case/config.h" #include "source/extensions/http/original_ip_detection/xff/config.h" +#include "source/extensions/network/dns_resolver/getaddrinfo/getaddrinfo.h" #include "source/extensions/stat_sinks/metrics_service/config.h" #include "source/extensions/transport_sockets/http_11_proxy/config.h" #include "source/extensions/transport_sockets/raw_buffer/config.h" @@ -69,6 +70,7 @@ void ExtensionRegistry::registerFactories() { Envoy::Upstream::forceRegisterLogicalDnsClusterFactory(); ExtensionRegistryPlatformAdditions::registerFactories(); Router::forceRegisterUpstreamCodecFilterFactory(); + Envoy::Network::forceRegisterGetAddrInfoDnsResolverFactory(); // TODO: add a "force initialize" function to the upstream code, or clean up the upstream code // in such a way that does not depend on the statically initialized variable. diff --git a/envoy_build_config/extensions_build_config.bzl b/envoy_build_config/extensions_build_config.bzl index 33eee6578b..c5159c1495 100644 --- a/envoy_build_config/extensions_build_config.bzl +++ b/envoy_build_config/extensions_build_config.bzl @@ -28,3 +28,4 @@ EXTENSIONS = { "envoy_mobile.cert_validator.platform_bridge_cert_validator": "@envoy_mobile//library/common/extensions/cert_validator/platform_bridge:config", } WINDOWS_EXTENSIONS = {} +LEGACY_ALWAYSLINK = 1 diff --git a/library/cc/engine_builder.cc b/library/cc/engine_builder.cc index 1d407e3863..f5a2b3812f 100644 --- a/library/cc/engine_builder.cc +++ b/library/cc/engine_builder.cc @@ -207,28 +207,18 @@ EngineBuilder& EngineBuilder::addStringAccessor(const std::string& name, return *this; } -std::string EngineBuilder::generateConfigStr() const { -#if defined(__APPLE__) - std::string dns_resolver_name = "envoy.network.dns_resolver.apple"; - std::string dns_resolver_config = - "{\"@type\":\"type.googleapis.com/" - "envoy.extensions.network.dns_resolver.apple.v3.AppleDnsResolverConfig\"}"; -#else - std::string dns_resolver_name = ""; - std::string dns_resolver_config = ""; - if (this->use_system_resolver_) { - dns_resolver_name = "envoy.network.dns_resolver.getaddrinfo"; - dns_resolver_config = - "{\"@type\":\"type.googleapis.com/" - "envoy.extensions.network.dns_resolver.getaddrinfo.v3.GetAddrInfoDnsResolverConfig\"}"; - } else { - dns_resolver_name = "envoy.network.dns_resolver.cares"; - dns_resolver_config = - "{\"@type\":\"type.googleapis.com/" - "envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig\"}"; - } -#endif +EngineBuilder& EngineBuilder::addNativeFilter(const std::string& name, + const std::string& typed_config) { + native_filter_chain_.emplace_back(name, typed_config); + return *this; +} +EngineBuilder& EngineBuilder::addPlatformFilter(const std::string& name) { + platform_filters_.push_back(name); + return *this; +} + +std::string EngineBuilder::generateConfigStr() const { std::vector> replacements { {"connect_timeout", fmt::format("{}s", this->connect_timeout_seconds_)}, {"dns_fail_base_interval", fmt::format("{}s", this->dns_failure_refresh_seconds_base_)}, @@ -239,7 +229,6 @@ std::string EngineBuilder::generateConfigStr() const { {"dns_preresolve_hostnames", this->dns_preresolve_hostnames_}, {"dns_refresh_rate", fmt::format("{}s", this->dns_refresh_seconds_)}, {"dns_query_timeout", fmt::format("{}s", this->dns_query_timeout_seconds_)}, - {"dns_resolver_name", dns_resolver_name}, {"dns_resolver_config", dns_resolver_config}, {"enable_drain_post_dns_refresh", enable_drain_post_dns_refresh_ ? "true" : "false"}, {"enable_interface_binding", enable_interface_binding_ ? "true" : "false"}, {"h2_connection_keepalive_idle_interval", @@ -301,6 +290,19 @@ std::string EngineBuilder::generateConfigStr() const { insertCustomFilter(alternate_protocols_cache_filter_insert, config_template); } + for (const NativeFilterConfig& filter : native_filter_chain_) { + std::string filter_config = absl::StrReplaceAll( + native_filter_template, {{"{{ native_filter_name }}", filter.name_}, + {"{{ native_filter_typed_config }}", filter.typed_config_}}); + insertCustomFilter(filter_config, config_template); + } + + for (const std::string& name : platform_filters_) { + std::string filter_config = + absl::StrReplaceAll(platform_filter_template, {{"{{ platform_filter_name }}", name}}); + insertCustomFilter(filter_config, config_template); + } + config_builder << config_template; if (admin_interface_enabled_) { diff --git a/library/cc/engine_builder.h b/library/cc/engine_builder.h index 775cc604a6..9b75f78e47 100644 --- a/library/cc/engine_builder.h +++ b/library/cc/engine_builder.h @@ -41,6 +41,10 @@ class EngineBuilder { EngineBuilder& addVirtualClusters(const std::string& virtual_clusters); EngineBuilder& addKeyValueStore(const std::string& name, KeyValueStoreSharedPtr key_value_store); EngineBuilder& addStringAccessor(const std::string& name, StringAccessorSharedPtr accessor); + EngineBuilder& addNativeFilter(const std::string& name, const std::string& typed_config); + // Configures Envoy to use the PlatformBridge filter named `name`. An instance of + // envoy_http_filter must be registered as a platform API with the same name. + EngineBuilder& addPlatformFilter(const std::string& name); EngineBuilder& setAppVersion(const std::string& app_version); EngineBuilder& setAppId(const std::string& app_id); EngineBuilder& setDeviceOs(const std::string& app_id); @@ -63,17 +67,19 @@ class EngineBuilder { EngineSharedPtr build(); - // TODO(crockeo): add after filter integration - // EngineBuilder& addPlatformFilter(name: String = UUID.randomUUID().toString(), factory: () -> - // Filter): - // EngineBuilder& addNativeFilter(name: String = UUID.randomUUID().toString(), - // typedConfig: String): - protected: void setOverrideConfigForTests(std::string config) { config_override_for_tests_ = config; } void setAdminAddressPathForTests(std::string admin) { admin_address_path_for_tests_ = admin; } private: + struct NativeFilterConfig { + NativeFilterConfig(const std::string& name, const std::string& typed_config) + : name_(name), typed_config_(typed_config) {} + + std::string name_; + std::string typed_config_; + }; + LogLevel log_level_ = LogLevel::info; EngineCallbacksSharedPtr callbacks_; @@ -115,9 +121,8 @@ class EngineBuilder { int max_connections_per_host_ = 7; std::vector stat_sinks_; - // TODO(crockeo): add after filter integration - // std::vector http_platform_filter_factories_; - // std::vector native_filter_chain_; + std::vector native_filter_chain_; + std::vector platform_filters_; absl::flat_hash_map string_accessors_; }; diff --git a/library/common/bridge/utility.h b/library/common/bridge/utility.h index 3798b1f2e3..7e5f8b3502 100644 --- a/library/common/bridge/utility.h +++ b/library/common/bridge/utility.h @@ -18,7 +18,8 @@ envoy_error_code_t errorCodeFromLocalStatus(Http::Code status); template envoy_map makeEnvoyMap(const T& map) { envoy_map new_map; new_map.length = std::size(map); - new_map.entries = new envoy_map_entry[std::size(map)]; + new_map.entries = + static_cast(safe_malloc(sizeof(envoy_map_entry) * std::size(map))); uint64_t i = 0; for (const auto& e : map) { diff --git a/library/common/config/config.cc b/library/common/config/config.cc index d7feba78e4..ad2cd92e01 100644 --- a/library/common/config/config.cc +++ b/library/common/config/config.cc @@ -114,8 +114,8 @@ R"(- &dns_resolver_name envoy.network.dns_resolver.apple - &dns_resolver_config {"@type":"type.googleapis.com/envoy.extensions.network.dns_resolver.apple.v3.AppleDnsResolverConfig"} )" #else -R"(- &dns_resolver_name envoy.network.dns_resolver.cares -- &dns_resolver_config {"@type":"type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig"} +R"(- &dns_resolver_name envoy.network.dns_resolver.getaddrinfo +- &dns_resolver_config {"@type":"type.googleapis.com/envoy.extensions.network.dns_resolver.getaddrinfo.v3.GetAddrInfoDnsResolverConfig"} )" #endif R"(- &enable_drain_post_dns_refresh false diff --git a/library/common/extensions/filters/http/platform_bridge/filter.cc b/library/common/extensions/filters/http/platform_bridge/filter.cc index 4aafebcb78..baea5572ad 100644 --- a/library/common/extensions/filters/http/platform_bridge/filter.cc +++ b/library/common/extensions/filters/http/platform_bridge/filter.cc @@ -167,28 +167,7 @@ void PlatformBridgeFilter::onDestroy() { ENVOY_LOG(trace, "PlatformBridgeFilter({})::onDestroy", filter_name_); alive_ = false; - auto& info = decoder_callbacks_->streamInfo(); - if (response_filter_base_->state_.stream_complete_ && platform_filter_.on_error && - StreamInfo::isStreamIdleTimeout(info)) { - // If the stream info has a response code details with a stream idle timeout, treat as error. - ENVOY_LOG(trace, "PlatformBridgeFilter({})->on_error", filter_name_); - envoy_data error_message = Data::Utility::copyToBridgeData("Stream idle timeout"); - auto& info = decoder_callbacks_->streamInfo(); - int32_t attempts = static_cast(info.attemptCount().value_or(0)); - - auto callback_time_ms = std::make_unique( - config_->stats().on_error_callback_latency_, timeSource()); - - platform_filter_.on_error({ENVOY_REQUEST_TIMEOUT, error_message, attempts}, streamIntel(), - finalStreamIntel(), platform_filter_.instance_context); - - callback_time_ms->complete(); - auto elapsed = callback_time_ms->elapsed(); - if (elapsed > SlowCallbackWarningThreshold) { - ENVOY_LOG_EVENT(warn, "slow_on_error_cb", - filter_name_ + "|" + std::to_string(elapsed.count()) + "ms"); - } - } else if (!response_filter_base_->state_.stream_complete_ && platform_filter_.on_cancel) { + if (!response_filter_base_->state_.stream_complete_ && platform_filter_.on_cancel) { // If the filter chain is destroyed before a response is received, treat as cancellation. ENVOY_LOG(trace, "PlatformBridgeFilter({})->on_cancel", filter_name_); diff --git a/library/common/jni/android_jni_interface.cc b/library/common/jni/android_jni_interface.cc index 9965195826..a1c1336fad 100644 --- a/library/common/jni/android_jni_interface.cc +++ b/library/common/jni/android_jni_interface.cc @@ -1,5 +1,3 @@ -#include - #include "library/common/jni/android_network_utility.h" #include "library/common/jni/import/jni_import.h" #include "library/common/jni/jni_support.h" @@ -13,21 +11,8 @@ extern "C" JNIEXPORT jint JNICALL Java_io_envoyproxy_envoymobile_engine_AndroidJniLibrary_initialize(JNIEnv* env, jclass, // class - jobject class_loader, - jobject connectivity_manager) { + jobject class_loader) { set_class_loader(env->NewGlobalRef(class_loader)); // At this point, we know Android APIs are available. Register cert chain validation JNI calls. - envoy_status_t result = - register_platform_api(cert_validator_name, get_android_cert_validator_api()); - if (result == ENVOY_FAILURE) { - return ENVOY_FAILURE; - } - - // See note above about c-ares. - // c-ares jvm init is necessary in order to let c-ares perform DNS resolution in Envoy. - // More information can be found at: - // https://c-ares.haxx.se/ares_library_init_android.html - ares_library_init_jvm(get_vm()); - - return ares_library_init_android(connectivity_manager); + return register_platform_api(cert_validator_name, get_android_cert_validator_api()); } diff --git a/library/common/jni/android_test_jni_interface.cc b/library/common/jni/android_test_jni_interface.cc index a04ddae3b1..a1c1336fad 100644 --- a/library/common/jni/android_test_jni_interface.cc +++ b/library/common/jni/android_test_jni_interface.cc @@ -11,8 +11,7 @@ extern "C" JNIEXPORT jint JNICALL Java_io_envoyproxy_envoymobile_engine_AndroidJniLibrary_initialize(JNIEnv* env, jclass, // class - jobject class_loader, - jobject connectivity_manager) { + jobject class_loader) { set_class_loader(env->NewGlobalRef(class_loader)); // At this point, we know Android APIs are available. Register cert chain validation JNI calls. return register_platform_api(cert_validator_name, get_android_cert_validator_api()); diff --git a/library/java/io/envoyproxy/envoymobile/engine/AndroidJniLibrary.java b/library/java/io/envoyproxy/envoymobile/engine/AndroidJniLibrary.java index 02e7cf8158..dae533e009 100644 --- a/library/java/io/envoyproxy/envoymobile/engine/AndroidJniLibrary.java +++ b/library/java/io/envoyproxy/envoymobile/engine/AndroidJniLibrary.java @@ -32,9 +32,7 @@ public static void load(Context context) { // its dependencies are loaded and initialized at most once. private static class AndroidLoader { private AndroidLoader(Context context) { - AndroidJniLibrary.initialize( - context.getClassLoader(), - (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE)); + AndroidJniLibrary.initialize(context.getClassLoader()); } } @@ -42,9 +40,7 @@ private AndroidLoader(Context context) { * Native binding to register the ConnectivityManager to C-Ares. * * @param classLoader Application's class loader. - * @param connectivityManager Android's ConnectivityManager. * @return The resulting status of the initialization. */ - protected static native int initialize(ClassLoader classLoader, - ConnectivityManager connectivityManager); + protected static native int initialize(ClassLoader classLoader); } diff --git a/library/java/io/envoyproxy/envoymobile/engine/AndroidNetworkMonitor.java b/library/java/io/envoyproxy/envoymobile/engine/AndroidNetworkMonitor.java index 4cf3a637f6..fc10cddc38 100644 --- a/library/java/io/envoyproxy/envoymobile/engine/AndroidNetworkMonitor.java +++ b/library/java/io/envoyproxy/envoymobile/engine/AndroidNetworkMonitor.java @@ -16,6 +16,7 @@ import android.net.NetworkInfo; import android.net.NetworkRequest; import android.os.Build; +import androidx.annotation.VisibleForTesting; import androidx.core.content.ContextCompat; import java.util.Collections; @@ -104,11 +105,20 @@ public void onLost(final Network network) { } } + /** @returns The singleton instance of {@link AndroidNetworkMonitor}. */ + public static AndroidNetworkMonitor getInstance() { + assert instance != null; + return instance; + } + @Override public void onReceive(Context context, Intent intent) { handleNetworkChange(); } + /** @returns True if there is connectivity */ + public boolean isOnline() { return previousNetworkType != -1; } + private void handleNetworkChange() { NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); int networkType = networkInfo == null ? -1 : networkInfo.getType(); @@ -128,4 +138,10 @@ private void handleNetworkChange() { envoyEngine.setPreferredNetwork(EnvoyNetworkType.ENVOY_NETWORK_TYPE_GENERIC); } } + + /** Expose connectivityManager only for testing */ + @VisibleForTesting + public ConnectivityManager getConnectivityManager() { + return connectivityManager; + } } diff --git a/library/java/io/envoyproxy/envoymobile/engine/BUILD b/library/java/io/envoyproxy/envoymobile/engine/BUILD index d42d805fdf..857d242a69 100644 --- a/library/java/io/envoyproxy/envoymobile/engine/BUILD +++ b/library/java/io/envoyproxy/envoymobile/engine/BUILD @@ -10,6 +10,7 @@ android_library( "AndroidJniLibrary.java", "AndroidNetworkMonitor.java", "AndroidProxyMonitor.java", + "UpstreamHttpProtocol.java", ], custom_package = "io.envoyproxy.envoymobile.engine", manifest = "AndroidEngineManifest.xml", @@ -18,6 +19,7 @@ android_library( "//library/java/io/envoyproxy/envoymobile/engine:envoy_base_engine_lib", "//library/java/io/envoyproxy/envoymobile/engine/types:envoy_c_types_lib", "//library/java/org/chromium/net", + "@maven//:androidx_annotation_annotation", "@maven//:androidx_core_core", ], ) diff --git a/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java b/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java index 7e0bc16468..d7a95c32e5 100644 --- a/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java +++ b/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java @@ -34,9 +34,6 @@ public enum TrustChainVerification { public final Integer dnsQueryTimeoutSeconds; public final Integer dnsMinRefreshSeconds; public final String dnsPreresolveHostnames; - public final List dnsFallbackNameservers; - public final Boolean dnsFilterUnroutableFamilies; - public final Boolean dnsUseSystemResolver; public final Boolean enableDrainPostDnsRefresh; public final Boolean enableHttp3; public final Boolean enableGzip; @@ -85,13 +82,6 @@ public enum TrustChainVerification { * refresh DNS. * @param dnsPreresolveHostnames hostnames to preresolve on Envoy Client * construction. - * @param dnsFallbackNameservers addresses to use as DNS name server - * fallback. - * @param dnsFilterUnroutableFamilies whether to filter unroutable IP families - * or not. - * @param dnsUseSystemResolver whether to use the getaddrinfo-based - * system resolver or - * c-ares. * @param enableDrainPostDnsRefresh whether to drain connections after soft * DNS refresh. * @param enableHttp3 whether to enable experimental support for @@ -133,13 +123,12 @@ public EnvoyConfiguration( boolean adminInterfaceEnabled, String grpcStatsDomain, int connectTimeoutSeconds, int dnsRefreshSeconds, int dnsFailureRefreshSecondsBase, int dnsFailureRefreshSecondsMax, int dnsQueryTimeoutSeconds, int dnsMinRefreshSeconds, String dnsPreresolveHostnames, - List dnsFallbackNameservers, boolean dnsFilterUnroutableFamilies, - boolean dnsUseSystemResolver, boolean enableDrainPostDnsRefresh, boolean enableHttp3, - boolean enableGzip, boolean enableBrotli, boolean enableSocketTagging, - boolean enableHappyEyeballs, boolean enableInterfaceBinding, - int h2ConnectionKeepaliveIdleIntervalMilliseconds, int h2ConnectionKeepaliveTimeoutSeconds, - boolean h2ExtendKeepaliveTimeout, int maxConnectionsPerHost, int statsFlushSeconds, - int streamIdleTimeoutSeconds, int perTryIdleTimeoutSeconds, String appVersion, String appId, + boolean enableDrainPostDnsRefresh, boolean enableHttp3, boolean enableGzip, + boolean enableBrotli, boolean enableSocketTagging, boolean enableHappyEyeballs, + boolean enableInterfaceBinding, int h2ConnectionKeepaliveIdleIntervalMilliseconds, + int h2ConnectionKeepaliveTimeoutSeconds, boolean h2ExtendKeepaliveTimeout, + int maxConnectionsPerHost, int statsFlushSeconds, int streamIdleTimeoutSeconds, + int perTryIdleTimeoutSeconds, String appVersion, String appId, TrustChainVerification trustChainVerification, String virtualClusters, List nativeFilterChain, List httpPlatformFilterFactories, @@ -155,9 +144,6 @@ public EnvoyConfiguration( this.dnsQueryTimeoutSeconds = dnsQueryTimeoutSeconds; this.dnsMinRefreshSeconds = dnsMinRefreshSeconds; this.dnsPreresolveHostnames = dnsPreresolveHostnames; - this.dnsFallbackNameservers = dnsFallbackNameservers; - this.dnsFilterUnroutableFamilies = dnsFilterUnroutableFamilies; - this.dnsUseSystemResolver = dnsUseSystemResolver; this.enableDrainPostDnsRefresh = enableDrainPostDnsRefresh; this.enableHttp3 = enableHttp3; this.enableGzip = enableGzip; @@ -235,33 +221,6 @@ String resolveTemplate(final String configTemplate, final String platformFilterT String processedTemplate = configTemplate.replace("#{custom_filters}", customFiltersBuilder.toString()); - String dnsFallbackNameserversAsString = "[]"; - if (!dnsFallbackNameservers.isEmpty()) { - StringBuilder sb = new StringBuilder("["); - String separator = ""; - for (String nameserver : dnsFallbackNameservers) { - sb.append(separator); - separator = ","; - sb.append(String.format("{\"socket_address\":{\"address\":\"%s\"}}", nameserver)); - } - sb.append("]"); - dnsFallbackNameserversAsString = sb.toString(); - } - - String dnsResolverName = ""; - String dnsResolverConfig = ""; - if (dnsUseSystemResolver) { - dnsResolverName = "envoy.network.dns_resolver.getaddrinfo"; - dnsResolverConfig = - "{\"@type\":\"type.googleapis.com/envoy.extensions.network.dns_resolver.getaddrinfo.v3.GetAddrInfoDnsResolverConfig\"}"; - } else { - dnsResolverName = "envoy.network.dns_resolver.cares"; - dnsResolverConfig = String.format( - "{\"@type\":\"type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig\",\"resolvers\":%s,\"use_resolvers_as_fallback\": %s, \"filter_unroutable_families\": %s}", - dnsFallbackNameserversAsString, !dnsFallbackNameservers.isEmpty() ? "true" : "false", - dnsFilterUnroutableFamilies ? "true" : "false"); - } - StringBuilder configBuilder = new StringBuilder("!ignore platform_defs:\n"); configBuilder.append(String.format("- &connect_timeout %ss\n", connectTimeoutSeconds)) .append(String.format("- &dns_fail_base_interval %ss\n", dnsFailureRefreshSecondsBase)) @@ -275,9 +234,7 @@ String resolveTemplate(final String configTemplate, final String platformFilterT String.format("- &dns_multiple_addresses %s\n", enableHappyEyeballs ? "true" : "false")) .append(String.format("- &h2_delay_keepalive_timeout %s\n", h2ExtendKeepaliveTimeout ? "true" : "false")) - .append(String.format("- &dns_resolver_name %s\n", dnsResolverName)) .append(String.format("- &dns_refresh_rate %ss\n", dnsRefreshSeconds)) - .append(String.format("- &dns_resolver_config %s\n", dnsResolverConfig)) .append(String.format("- &enable_drain_post_dns_refresh %s\n", enableDrainPostDnsRefresh ? "true" : "false")) .append(String.format("- &enable_interface_binding %s\n", diff --git a/library/java/io/envoyproxy/envoymobile/engine/UpstreamHttpProtocol.java b/library/java/io/envoyproxy/envoymobile/engine/UpstreamHttpProtocol.java new file mode 100644 index 0000000000..1153d5b1df --- /dev/null +++ b/library/java/io/envoyproxy/envoymobile/engine/UpstreamHttpProtocol.java @@ -0,0 +1,20 @@ +package io.envoyproxy.envoymobile.engine; + +import androidx.annotation.LongDef; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * The upstream protocol, if an upstream connection was established. Field + * entries are based off of Envoy's Http::Protocol + * https://github.com/envoyproxy/envoy/blob/main/envoy/http/protocol.h + */ +@LongDef({UpstreamHttpProtocol.HTTP10, UpstreamHttpProtocol.HTTP11, UpstreamHttpProtocol.HTTP2, + UpstreamHttpProtocol.HTTP3}) +@Retention(RetentionPolicy.SOURCE) +public @interface UpstreamHttpProtocol { + long HTTP10 = 0; + long HTTP11 = 1; + long HTTP2 = 2; + long HTTP3 = 3; +} diff --git a/library/java/org/chromium/net/BUILD b/library/java/org/chromium/net/BUILD index b0319df3d3..449228419d 100644 --- a/library/java/org/chromium/net/BUILD +++ b/library/java/org/chromium/net/BUILD @@ -23,6 +23,7 @@ android_binary( name = "cronet", srcs = [], manifest = "ChromiumNetManifest.xml", + proguard_specs = ["//library:proguard_rules"], visibility = ["//visibility:public"], deps = [ ":net", diff --git a/library/java/org/chromium/net/impl/CronetBidirectionalStream.java b/library/java/org/chromium/net/impl/CronetBidirectionalStream.java index b72ed3042c..76ff33624d 100644 --- a/library/java/org/chromium/net/impl/CronetBidirectionalStream.java +++ b/library/java/org/chromium/net/impl/CronetBidirectionalStream.java @@ -653,13 +653,13 @@ private void onErrorReceived(int errorCode, EnvoyFinalStreamIntel finalStreamInt mResponseInfo.setReceivedByteCount(finalStreamIntel.getReceivedByteCount()); } - NetError netError = mapEnvoyMobileErrorToNetError(finalStreamIntel.getResponseFlags()); + NetError netError = mapEnvoyMobileErrorToNetError(finalStreamIntel); int javaError = mapNetErrorToCronetApiErrorCode(netError); if (isQuicException(javaError)) { mException.set(new QuicExceptionImpl("Exception in BidirectionalStream: " + netError, javaError, netError.getErrorCode(), - /*nativeQuicError*/ 0)); + Errors.QUIC_INTERNAL_ERROR)); } else { mException.set(new BidirectionalStreamNetworkException( "Exception in BidirectionalStream: " + netError, javaError, netError.getErrorCode())); diff --git a/library/java/org/chromium/net/impl/CronetUrlRequest.java b/library/java/org/chromium/net/impl/CronetUrlRequest.java index e9b27db1dc..3837593bc1 100644 --- a/library/java/org/chromium/net/impl/CronetUrlRequest.java +++ b/library/java/org/chromium/net/impl/CronetUrlRequest.java @@ -934,13 +934,13 @@ public void onError(int errorCode, String message, int attemptCount, return; } - NetError netError = mapEnvoyMobileErrorToNetError(finalStreamIntel.getResponseFlags()); + NetError netError = mapEnvoyMobileErrorToNetError(finalStreamIntel); int javaError = mapNetErrorToCronetApiErrorCode(netError); if (isQuicException(javaError)) { enterErrorState(new QuicExceptionImpl("Exception in CronetUrlRequest: " + netError, javaError, netError.getErrorCode(), - /*nativeQuicError*/ 0)); + Errors.QUIC_INTERNAL_ERROR)); return; } diff --git a/library/java/org/chromium/net/impl/Errors.java b/library/java/org/chromium/net/impl/Errors.java index 85add92f5c..f820635253 100644 --- a/library/java/org/chromium/net/impl/Errors.java +++ b/library/java/org/chromium/net/impl/Errors.java @@ -2,6 +2,9 @@ import android.util.Log; import androidx.annotation.LongDef; +import io.envoyproxy.envoymobile.engine.AndroidNetworkMonitor; +import io.envoyproxy.envoymobile.engine.UpstreamHttpProtocol; +import io.envoyproxy.envoymobile.engine.types.EnvoyFinalStreamIntel; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Collections; @@ -14,6 +17,8 @@ * from Envoymobile error to Chromium neterror and finally to the public Network Exception. */ public class Errors { + // This represents a nativeQuicError since we don't expose individual quic errors yet. + public static final int QUIC_INTERNAL_ERROR = 1; private static final Map ENVOYMOBILE_ERROR_TO_NET_ERROR = buildErrorMap(); /**Subset of errors defined in @@ -67,13 +72,20 @@ public String toString() { * @param responseFlag envoymobile's finalStreamIntel responseFlag * @return the NetError that the EnvoyMobileError maps to */ - public static NetError mapEnvoyMobileErrorToNetError(long responseFlag) { - /* Todo(https://github.com/envoyproxy/envoy-mobile/issues/1594): - * if (EnvoyMobileError.DNS_RESOLUTION_FAILED || EnvoyMobileError.UPSTREAM_CONNECTION_FAILURE) - * && NetworkChangeNotifier.isOffline return NetError.ERR_INTERNET_DISCONNECTED - * - * if negotiated_protocol is quic return QUIC_PROTOCOL_FAILED - */ + public static NetError mapEnvoyMobileErrorToNetError(EnvoyFinalStreamIntel finalStreamIntel) { + // if connection fails to be established, check if user is offline + long responseFlag = finalStreamIntel.getResponseFlags(); + if ((responseFlag == EnvoyMobileError.DNS_RESOLUTION_FAILED || + responseFlag == EnvoyMobileError.UPSTREAM_CONNECTION_FAILURE) && + !AndroidNetworkMonitor.getInstance().isOnline()) { + return NetError.ERR_INTERNET_DISCONNECTED; + } + + // Check if negotiated_protocol is quic + if (finalStreamIntel.getUpstreamProtocol() == UpstreamHttpProtocol.HTTP3) { + return NetError.ERR_QUIC_PROTOCOL_ERROR; + } + return ENVOYMOBILE_ERROR_TO_NET_ERROR.getOrDefault(responseFlag, NetError.ERR_OTHER); } diff --git a/library/java/org/chromium/net/impl/NativeCronetEngineBuilderImpl.java b/library/java/org/chromium/net/impl/NativeCronetEngineBuilderImpl.java index 1da9dff179..9f1300c1fb 100644 --- a/library/java/org/chromium/net/impl/NativeCronetEngineBuilderImpl.java +++ b/library/java/org/chromium/net/impl/NativeCronetEngineBuilderImpl.java @@ -122,9 +122,8 @@ private EnvoyConfiguration createEnvoyConfiguration() { return new EnvoyConfiguration( mAdminInterfaceEnabled, mGrpcStatsDomain, mConnectTimeoutSeconds, mDnsRefreshSeconds, mDnsFailureRefreshSecondsBase, mDnsFailureRefreshSecondsMax, mDnsQueryTimeoutSeconds, - mDnsMinRefreshSeconds, mDnsPreresolveHostnames, mDnsFallbackNameservers, - mEnableDnsFilterUnroutableFamilies, mDnsUseSystemResolver, mEnableDrainPostDnsRefresh, - quicEnabled(), mEnableGzip, brotliEnabled(), mEnableSocketTag, mEnableHappyEyeballs, + mDnsMinRefreshSeconds, mDnsPreresolveHostnames, mEnableDrainPostDnsRefresh, quicEnabled(), + mEnableGzip, brotliEnabled(), mEnableSocketTag, mEnableHappyEyeballs, mEnableInterfaceBinding, mH2ConnectionKeepaliveIdleIntervalMilliseconds, mH2ConnectionKeepaliveTimeoutSeconds, mH2ExtendKeepaliveTimeout, mMaxConnectionsPerHost, mStatsFlushSeconds, mStreamIdleTimeoutSeconds, mPerTryIdleTimeoutSeconds, mAppVersion, diff --git a/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt b/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt index 15784a18d8..b1121f1665 100644 --- a/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt +++ b/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt @@ -48,9 +48,6 @@ open class EngineBuilder( private var dnsRefreshSeconds = 60 private var dnsFailureRefreshSecondsBase = 2 private var dnsFailureRefreshSecondsMax = 10 - private var dnsFallbackNameservers = listOf() - private var dnsFilterUnroutableFamilies = true - private var dnsUseSystemResolver = true private var dnsQueryTimeoutSeconds = 25 private var dnsMinRefreshSeconds = 60 private var dnsPreresolveHostnames = "[]" @@ -196,47 +193,6 @@ open class EngineBuilder( return this } - /** - * Add a list of IP addresses to use as fallback DNS name servers. - * - * @param dnsFallbackNameservers addresses to use. - * - * @return this builder. - */ - fun addDNSFallbackNameservers(dnsFallbackNameservers: List): EngineBuilder { - this.dnsFallbackNameservers = dnsFallbackNameservers - return this - } - - /** - * Specify whether to filter unroutable IP families during DNS resolution or not. - * Defaults to true. - * - * @param dnsFilterUnroutableFamilies whether to filter or not. - * - * @return this builder. - */ - fun enableDNSFilterUnroutableFamilies(dnsFilterUnroutableFamilies: Boolean): EngineBuilder { - this.dnsFilterUnroutableFamilies = dnsFilterUnroutableFamilies - return this - } - - /** - * Specify whether to use the getaddrinfo-based system DNS resolver or the c-ares resolver. - * Defaults to true. - * - * Note that if this is set, the values of `dnsFallbackNameservers` and - * `dnsFilterUnroutableFamilies` will be ignored. - * - * @param dnsUseSystemResolver whether to use the system DNS resolver. - * - * @return this builder. - */ - fun enableDNSUseSystemResolver(dnsUseSystemResolver: Boolean): EngineBuilder { - this.dnsUseSystemResolver = dnsUseSystemResolver - return this - } - /** * Specify whether to drain connections after the resolution of a soft DNS refresh. A refresh may * be triggered directly via the Engine API, or as a result of a network status update provided by @@ -628,9 +584,6 @@ open class EngineBuilder( dnsQueryTimeoutSeconds, dnsMinRefreshSeconds, dnsPreresolveHostnames, - dnsFallbackNameservers, - dnsFilterUnroutableFamilies, - dnsUseSystemResolver, enableDrainPostDnsRefresh, enableHttp3, enableGzip, diff --git a/library/objective-c/EnvoyConfiguration.m b/library/objective-c/EnvoyConfiguration.m index 54169d42ab..df43f48efc 100644 --- a/library/objective-c/EnvoyConfiguration.m +++ b/library/objective-c/EnvoyConfiguration.m @@ -162,11 +162,6 @@ - (nullable NSString *)resolveTemplate:(NSString *)templateYAML { [definitions appendFormat:@"- &dns_refresh_rate %lus\n", (unsigned long)self.dnsRefreshSeconds]; [definitions appendFormat:@"- &enable_drain_post_dns_refresh %@\n", self.enableDrainPostDnsRefresh ? @"true" : @"false"]; - // No additional values are currently needed for Apple-based DNS resolver. - [definitions - appendFormat:@"- &dns_resolver_config " - @"{\"@type\":\"type.googleapis.com/" - @"envoy.extensions.network.dns_resolver.apple.v3.AppleDnsResolverConfig\"}\n"]; [definitions appendFormat:@"- &enable_interface_binding %@\n", self.enableInterfaceBinding ? @"true" : @"false"]; [definitions appendFormat:@"- &trust_chain_verification %@\n", self.enforceTrustChainVerification diff --git a/library/python/BUILD b/library/python/BUILD index 116344ac44..f25b270e21 100644 --- a/library/python/BUILD +++ b/library/python/BUILD @@ -1,4 +1,4 @@ -load("@pip//:requirements.bzl", "requirement") +load("@mobile_pip3//:requirements.bzl", "requirement") load("@pybind11_bazel//:build_defs.bzl", "pybind_extension", "pybind_library") load("@python_abi//:abi.bzl", "abi_tag", "python_tag") load("@rules_python//python:defs.bzl", "py_library") diff --git a/library/python/envoy_requests/asyncio.py b/library/python/envoy_requests/asyncio.py index 8ede9d79d6..a0aa29f1ae 100644 --- a/library/python/envoy_requests/asyncio.py +++ b/library/python/envoy_requests/asyncio.py @@ -30,7 +30,10 @@ async def request(*args, **kwargs) -> Response: await engine_running.wait() stream = make_stream( - engine, executor, response, lambda: stream_complete.set(), + engine, + executor, + response, + lambda: stream_complete.set(), ) send_request(stream, *args, **kwargs) await stream_complete.wait() @@ -73,10 +76,12 @@ async def trace(*args, **kwargs) -> Response: class AsyncioExecutor(Executor): + def __init__(self): self.loop = asyncio.get_running_loop() def wrap(self, fn: Func) -> Func: + @functools.wraps(fn) def wrapper(*args, **kwargs): self.loop.call_soon_threadsafe(fn, *args, **kwargs) diff --git a/library/python/envoy_requests/common/core.py b/library/python/envoy_requests/common/core.py index 4225ea1497..4c16e38276 100644 --- a/library/python/envoy_requests/common/core.py +++ b/library/python/envoy_requests/common/core.py @@ -14,7 +14,6 @@ from ..response import Response from .executor import Executor - Data = Optional[Union[bytes, str, Dict[str, Any], List[Tuple[str, Any]]]] NormalData = bytes @@ -31,7 +30,9 @@ def make_stream( response: Response, set_stream_complete: Callable[[], None], ): - def _on_headers(headers: envoy_engine.ResponseHeaders, _: bool, intel: envoy_engine.StreamIntel): + + def _on_headers( + headers: envoy_engine.ResponseHeaders, _: bool, intel: envoy_engine.StreamIntel): response.status_code = headers.http_status() for key in headers: value = headers[key] @@ -48,7 +49,9 @@ def _on_data(data: bytes, _: bool): def _on_complete(intel: envoy_engine.StreamIntel, _: envoy_engine.FinalStreamIntel): set_stream_complete() - def _on_error(error: envoy_engine.EnvoyError, intel: envoy_engine.StreamIntel, _: envoy_engine.FinalStreamIntel): + def _on_error( + error: envoy_engine.EnvoyError, intel: envoy_engine.StreamIntel, + _: envoy_engine.FinalStreamIntel): response.envoy_error = error set_stream_complete() @@ -56,16 +59,12 @@ def _on_cancel(intel: envoy_engine.StreamIntel, _: envoy_engine.FinalStreamIntel set_stream_complete() return ( - engine.stream_client() - .new_stream_prototype() - .set_on_headers(executor.wrap(_on_headers)) - .set_on_data(executor.wrap(_on_data)) - .set_on_trailers(executor.wrap(_on_trailers)) - .set_on_complete(executor.wrap(_on_complete)) - .set_on_error(executor.wrap(_on_error)) - .set_on_cancel(executor.wrap(_on_cancel)) - .start(False) - ) + engine.stream_client().new_stream_prototype().set_on_headers( + executor.wrap(_on_headers)).set_on_data(executor.wrap(_on_data)).set_on_trailers( + executor.wrap(_on_trailers)).set_on_complete( + executor.wrap(_on_complete)).set_on_error( + executor.wrap(_on_error)).set_on_cancel( + executor.wrap(_on_cancel)).start(False)) def send_request( @@ -92,9 +91,7 @@ def send_request( structured_url.path, ) if norm_timeout_ms > 0: - request_headers_builder.add( - "x-envoy-upstream-rq-timeout-ms", str(norm_timeout_ms) - ) + request_headers_builder.add("x-envoy-upstream-rq-timeout-ms", str(norm_timeout_ms)) for key, values in norm_headers.items(): for value in values: request_headers_builder.add(key, value) diff --git a/library/python/envoy_requests/common/engine.py b/library/python/envoy_requests/common/engine.py index dc34647ba8..be8b350b85 100644 --- a/library/python/envoy_requests/common/engine.py +++ b/library/python/envoy_requests/common/engine.py @@ -23,9 +23,7 @@ def build(cls, executor: Executor, set_engine_running: Callable[[], None]): cls._handle = ( engine_builder.add_log_level(cls.log_level).set_on_engine_running( - executor.wrap(set_engine_running) - ) - ).build() + executor.wrap(set_engine_running))).build() atexit.register(lambda: cls._handle.terminate()) @classmethod diff --git a/library/python/envoy_requests/common/executor.py b/library/python/envoy_requests/common/executor.py index 499572669c..611de62e65 100644 --- a/library/python/envoy_requests/common/executor.py +++ b/library/python/envoy_requests/common/executor.py @@ -4,7 +4,6 @@ from typing import Callable from typing import TypeVar - Func = TypeVar("Func", bound=Callable[..., Any]) diff --git a/library/python/envoy_requests/gevent.py b/library/python/envoy_requests/gevent.py index bd535c92ba..2f3d0280ff 100644 --- a/library/python/envoy_requests/gevent.py +++ b/library/python/envoy_requests/gevent.py @@ -38,7 +38,10 @@ def request(*args, **kwargs) -> Response: engine_running.wait() stream = make_stream( - engine, executor, response, lambda: stream_complete.set(), + engine, + executor, + response, + lambda: stream_complete.set(), ) send_request(stream, *args, **kwargs) stream_complete.wait() @@ -82,17 +85,17 @@ def trace(*args, **kwargs) -> Response: class GeventExecutor(Executor): + def __init__(self): self.group = Group() - self.channel: GeventChannel[ - Tuple[Callable, List[Any], Dict[str, Any]] - ] = GeventChannel() + self.channel: GeventChannel[Tuple[Callable, List[Any], Dict[str, Any]]] = GeventChannel() self.spawn_work_greenlet = gevent.spawn(self._spawn_work) def __del__(self): self.spawn_work_greenlet.kill() def wrap(self, fn: Func) -> Func: + @functools.wraps(fn) def wrapper(*args, **kwargs): self.channel.put((fn, args, kwargs)) @@ -106,6 +109,7 @@ def _spawn_work(self): class GeventChannel(Generic[T]): + def __init__(self): self.hub = gevent.get_hub() self.watcher = self.hub.loop.async_() diff --git a/library/python/envoy_requests/response.py b/library/python/envoy_requests/response.py index 829b77b962..ac94489aac 100644 --- a/library/python/envoy_requests/response.py +++ b/library/python/envoy_requests/response.py @@ -9,6 +9,7 @@ class Response: + def __init__(self): self.body_raw = bytearray() self.status_code: Optional[int] = None diff --git a/library/python/envoy_requests/threading.py b/library/python/envoy_requests/threading.py index 6aac216e48..279c743beb 100644 --- a/library/python/envoy_requests/threading.py +++ b/library/python/envoy_requests/threading.py @@ -34,7 +34,10 @@ def request(*args, **kwargs) -> Response: engine_running.wait() stream = make_stream( - engine, executor, response, lambda: stream_complete.set(), + engine, + executor, + response, + lambda: stream_complete.set(), ) send_request(stream, *args, **kwargs) stream_complete.wait() @@ -77,10 +80,12 @@ def trace(*args, **kwargs) -> Response: class ThreadingExecutor(Executor): + def __init__(self): self.lock = Lock() def wrap(self, fn: Func) -> Func: + @functools.wraps(fn) def wrapper(*args, **kwargs): with self.lock: diff --git a/library/python/gevent_util/__init__.py b/library/python/gevent_util/__init__.py index f062933f31..4da8374882 100644 --- a/library/python/gevent_util/__init__.py +++ b/library/python/gevent_util/__init__.py @@ -17,7 +17,6 @@ from library.python.envoy_engine import StreamClient from library.python.envoy_engine import StreamPrototype - T = TypeVar("T") @@ -29,6 +28,7 @@ # a base class's fields rather than manually writing out all of the properties # and methods. class CompositionalInheritor(Generic[T]): + def __init__(self, base: T): self.base = base @@ -39,6 +39,7 @@ def __getattr__(self, name: str): # we have to define wrappers around everything from EngineBuilder -> StreamPrototype # in order to wrap all callbacks in the GeventExecutor class GeventEngineBuilder(EngineBuilder): + def __init__(self): super().__init__() self.executor = GeventExecutor() @@ -52,6 +53,7 @@ def build(self) -> "GeventEngine": class GeventEngine(CompositionalInheritor[Engine]): + def __init__(self, base: Engine): super().__init__(base) @@ -60,6 +62,7 @@ def stream_client(self) -> "GeventStreamClient": class GeventStreamClient(CompositionalInheritor[StreamClient]): + def __init__(self, base: StreamClient): super().__init__(base) @@ -68,11 +71,13 @@ def new_stream_prototype(self) -> "GeventStreamPrototype": class GeventStreamPrototype(CompositionalInheritor[StreamPrototype]): + def __init__(self, base: StreamClient): super().__init__(base) self.executor = GeventExecutor() - def set_on_headers(self, closure: Callable[[ResponseHeaders, bool], None]) -> "GeventStreamPrototype": + def set_on_headers( + self, closure: Callable[[ResponseHeaders, bool], None]) -> "GeventStreamPrototype": self.base.set_on_headers(self.executor(closure)) return self @@ -80,7 +85,8 @@ def set_on_data(self, closure: Callable[[bytes, bool], None]) -> "GeventStreamPr self.base.set_on_data(self.executor(closure)) return self - def set_on_trailers(self, closure: Callable[[ResponseTrailers, bool], None]) -> "GeventStreamPrototype": + def set_on_trailers( + self, closure: Callable[[ResponseTrailers, bool], None]) -> "GeventStreamPrototype": self.base.set_on_trailers(self.executor(closure)) return self @@ -98,10 +104,12 @@ def set_on_cancel(self, closure: Callable[[], None]) -> "GeventStreamPrototype": class GeventExecutor(): + def __init__(self): super().__init__() self.group = Group() - self.channel: ThreadsafeChannel[Tuple[Callable, List[Any], Dict[str, Any]]] = ThreadsafeChannel() + self.channel: ThreadsafeChannel[Tuple[Callable, List[Any], + Dict[str, Any]]] = ThreadsafeChannel() self.spawn_work_greenlet = gevent.spawn(self._spawn_work) def __del__(self): @@ -109,9 +117,11 @@ def __del__(self): self.spawn_work_greenlet.kill() def __call__(self, fn: Callable) -> Callable: + @functools.wraps(fn) def wrapper(*args, **kwargs): self.channel.put((fn, args, kwargs)) + return wrapper def _spawn_work(self): @@ -121,6 +131,7 @@ def _spawn_work(self): class ThreadsafeChannel(Generic[T]): + def __init__(self): self.hub = gevent.get_hub() self.watcher = self.hub.loop.async_() diff --git a/test/cc/unit/envoy_config_test.cc b/test/cc/unit/envoy_config_test.cc index 97537c2c6b..abd0c4bac0 100644 --- a/test/cc/unit/envoy_config_test.cc +++ b/test/cc/unit/envoy_config_test.cc @@ -80,19 +80,6 @@ TEST(TestConfig, ConfigIsValid) { #endif } -#if !defined(__APPLE__) -TEST(TestConfig, SetUseDnsCAresResolver) { - EngineBuilder engine_builder; - engine_builder.useDnsSystemResolver(false); - std::string config_str = engine_builder.generateConfigStr(); - envoy::config::bootstrap::v3::Bootstrap bootstrap; - TestUtility::loadFromYaml(absl::StrCat(config_header, config_str), bootstrap); - - ASSERT_THAT(bootstrap.DebugString(), HasSubstr("envoy.network.dns_resolver.cares")); - ASSERT_THAT(bootstrap.DebugString(), Not(HasSubstr("envoy.network.dns_resolver.getaddrinfo"))); -} -#endif - TEST(TestConfig, SetGzip) { EngineBuilder engine_builder; @@ -376,7 +363,49 @@ class TestStringAccessor : public StringAccessor { mutable int count_ = 0; }; -TEST(TestConfig, StringAccessors) { +TEST(TestConfig, AddNativeFilter) { + EngineBuilder engine_builder; + + std::string filter_name = "envoy.filters.http.buffer"; + std::string filter_config = + "{\"@type\":\"type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer\"," + "\"max_request_bytes\":5242880}"; + + std::string config_str = engine_builder.generateConfigStr(); + ASSERT_THAT(config_str, Not(HasSubstr("- name: " + filter_name))); + ASSERT_THAT(config_str, Not(HasSubstr(" typed_config: " + filter_config))); + envoy::config::bootstrap::v3::Bootstrap bootstrap; + TestUtility::loadFromYaml(absl::StrCat(config_header, config_str), bootstrap); + + engine_builder.addNativeFilter(filter_name, filter_config); + + config_str = engine_builder.generateConfigStr(); + ASSERT_THAT(config_str, HasSubstr("- name: " + filter_name)); + ASSERT_THAT(config_str, HasSubstr(" typed_config: " + filter_config)); + TestUtility::loadFromYaml(absl::StrCat(config_header, config_str), bootstrap); +} + +TEST(TestConfig, AddPlatformFilter) { + EngineBuilder engine_builder; + + std::string filter_name = "test_platform_filter"; + + std::string config_str = engine_builder.generateConfigStr(); + ASSERT_THAT(config_str, Not(HasSubstr("http.platform_bridge.PlatformBridge"))); + ASSERT_THAT(config_str, Not(HasSubstr("platform_filter_name: " + filter_name))); + envoy::config::bootstrap::v3::Bootstrap bootstrap; + TestUtility::loadFromYaml(absl::StrCat(config_header, config_str), bootstrap); + + engine_builder.addPlatformFilter(filter_name); + + config_str = engine_builder.generateConfigStr(); + ASSERT_THAT(config_str, HasSubstr("http.platform_bridge.PlatformBridge")); + ASSERT_THAT(config_str, HasSubstr("platform_filter_name: " + filter_name)); + TestUtility::loadFromYaml(absl::StrCat(config_header, config_str), bootstrap); +} + +// TODO(RyanTheOptimist): This test seems to be flaky. #2641 +TEST(TestConfig, DISABLED_StringAccessors) { std::string name("accessor_name"); EngineBuilder engine_builder; std::string data_string = "envoy string"; diff --git a/test/common/http/BUILD b/test/common/http/BUILD index 135b7e9b2c..c190fd0df8 100644 --- a/test/common/http/BUILD +++ b/test/common/http/BUILD @@ -29,6 +29,7 @@ envoy_cc_test( srcs = ["header_utility_test.cc"], repository = "@envoy", deps = [ + "//library/common/bridge:utility_lib", "//library/common/data:utility_lib", "//library/common/http:header_utility_lib", "//library/common/types:c_types_lib", diff --git a/test/common/http/header_utility_test.cc b/test/common/http/header_utility_test.cc index eea887c3a2..4b601a3066 100644 --- a/test/common/http/header_utility_test.cc +++ b/test/common/http/header_utility_test.cc @@ -1,6 +1,7 @@ #include "source/common/http/header_map_impl.h" #include "gtest/gtest.h" +#include "library/common/bridge/utility.h" #include "library/common/data/utility.h" #include "library/common/http/header_utility.h" #include "library/common/types/c_types.h" @@ -18,8 +19,8 @@ envoy_data envoyTestString(std::string& s, uint32_t* sentinel) { } TEST(RequestHeaderDataConstructorTest, FromCToCppEmpty) { - envoy_map_entry* header_array = new envoy_map_entry[0]; - envoy_headers empty_headers = {0, header_array}; + std::map empty_map; + envoy_headers empty_headers = Bridge::Utility::makeEnvoyMap(empty_map); RequestHeaderMapPtr cpp_headers = Utility::toRequestHeaders(empty_headers); @@ -27,8 +28,8 @@ TEST(RequestHeaderDataConstructorTest, FromCToCppEmpty) { } TEST(RequestTrailerDataConstructorTest, FromCToCppEmpty) { - envoy_map_entry* header_array = new envoy_map_entry[0]; - envoy_headers empty_trailers = {0, header_array}; + std::map empty_map; + envoy_headers empty_trailers = Bridge::Utility::makeEnvoyMap(empty_map); RequestTrailerMapPtr cpp_trailers = Utility::toRequestTrailers(empty_trailers); @@ -40,7 +41,8 @@ TEST(RequestHeaderDataConstructorTest, FromCToCpp) { std::vector> headers = { {":method", "GET"}, {":scheme", "https"}, {":authority", "api.lyft.com"}, {":path", "/ping"}}; - envoy_map_entry* header_array = new envoy_map_entry[headers.size()]; + envoy_map_entry* header_array = + static_cast(safe_malloc(sizeof(envoy_map_entry) * headers.size())); uint32_t* sentinel = new uint32_t; *sentinel = 0; @@ -81,7 +83,8 @@ TEST(RequestTrailerDataConstructorTest, FromCToCpp) { std::vector> trailers = { {"processing-duration-ms", "25"}, {"response-compression-ratio", "0.61"}}; - envoy_map_entry* header_array = new envoy_map_entry[trailers.size()]; + envoy_map_entry* header_array = + static_cast(safe_malloc(sizeof(envoy_map_entry) * trailers.size())); uint32_t* sentinel = new uint32_t; *sentinel = 0; @@ -105,9 +108,8 @@ TEST(RequestTrailerDataConstructorTest, FromCToCpp) { ASSERT_EQ(cpp_trailers->size(), c_trailers_copy.length); for (envoy_map_size_t i = 0; i < c_trailers_copy.length; i++) { - auto expected_key = - LowerCaseString(Data::Utility::copyToString(c_trailers_copy.entries[i].key)); - auto expected_value = Data::Utility::copyToString(c_trailers_copy.entries[i].value); + LowerCaseString expected_key(Data::Utility::copyToString(c_trailers_copy.entries[i].key)); + std::string expected_value = Data::Utility::copyToString(c_trailers_copy.entries[i].value); // Key is present. EXPECT_FALSE(cpp_trailers->get(expected_key).empty()); @@ -137,8 +139,8 @@ TEST(HeaderDataConstructorTest, FromCppToC) { ASSERT_EQ(c_headers.length, static_cast(cpp_headers->size())); for (envoy_map_size_t i = 0; i < c_headers.length; i++) { - auto actual_key = LowerCaseString(Data::Utility::copyToString(c_headers.entries[i].key)); - auto actual_value = Data::Utility::copyToString(c_headers.entries[i].value); + LowerCaseString actual_key(Data::Utility::copyToString(c_headers.entries[i].key)); + std::string actual_value = Data::Utility::copyToString(c_headers.entries[i].value); // Key is present. EXPECT_FALSE(cpp_headers->get(actual_key).empty()); @@ -162,8 +164,8 @@ TEST(HeaderDataConstructorTest, FromCppToCWithAlpn) { ASSERT_EQ(c_headers.length, static_cast(cpp_headers->size())); for (envoy_map_size_t i = 0; i < c_headers.length; i++) { - auto actual_key = LowerCaseString(Data::Utility::copyToString(c_headers.entries[i].key)); - auto actual_value = Data::Utility::copyToString(c_headers.entries[i].value); + LowerCaseString actual_key(Data::Utility::copyToString(c_headers.entries[i].key)); + std::string actual_value = Data::Utility::copyToString(c_headers.entries[i].value); // Key is present. EXPECT_FALSE(cpp_headers->get(actual_key).empty()); diff --git a/test/integration/filters/http/test_read/filter.cc b/test/integration/filters/http/test_read/filter.cc index 1803da2dd1..251d952294 100644 --- a/test/integration/filters/http/test_read/filter.cc +++ b/test/integration/filters/http/test_read/filter.cc @@ -8,17 +8,30 @@ namespace TestRead { Http::FilterHeadersStatus TestReadFilter::decodeHeaders(Http::RequestHeaderMap& request_headers, bool) { - // sample path is /failed?start=0x10000 + // sample path is /failed?error=0x10000 Http::Utility::QueryParams query_parameters = Http::Utility::parseQueryString(request_headers.Path()->value().getStringView()); + auto error = query_parameters.find("error"); uint64_t response_flag; - if (absl::SimpleAtoi(query_parameters.at("start"), &response_flag)) { - decoder_callbacks_->streamInfo().setResponseFlag( - TestReadFilter::mapErrorToResponseFlag(response_flag)); + if (error != query_parameters.end() && absl::SimpleAtoi(error->second, &response_flag)) { + // set response error code + StreamInfo::StreamInfo& stream_info = decoder_callbacks_->streamInfo(); + stream_info.setResponseFlag(TestReadFilter::mapErrorToResponseFlag(response_flag)); + + // check if we want a quic server error: sample path is /failed?quic=1&error=0x10000 + if (query_parameters.find("quic") != query_parameters.end()) { + stream_info.setUpstreamInfo(std::make_shared()); + stream_info.upstreamInfo()->setUpstreamProtocol(Http::Protocol::Http3); + } + + // trigger the error and stop iteration to other filters decoder_callbacks_->sendLocalReply(Http::Code::BadRequest, "test_read filter threw: ", nullptr, absl::nullopt, ""); + return Http::FilterHeadersStatus::StopIteration; } - return Http::FilterHeadersStatus::StopIteration; + + // continue to other filters since the provided query string is invalid for error simulation + return Http::FilterHeadersStatus::Continue; } StreamInfo::ResponseFlag TestReadFilter::mapErrorToResponseFlag(uint64_t errorCode) { diff --git a/test/integration/filters/http/test_read/filter.h b/test/integration/filters/http/test_read/filter.h index c65dd7d5de..e394866e7b 100644 --- a/test/integration/filters/http/test_read/filter.h +++ b/test/integration/filters/http/test_read/filter.h @@ -14,7 +14,9 @@ namespace HttpFilters { namespace TestRead { /** - * This is a test-only filter to return specified error code based on a request header. + * This is a test-only filter to return specified error code based on a request url query string. + * It either simulates the requested error if the url query matches the error patterns + * or does nothing */ class TestReadFilter final : public Http::PassThroughFilter, public Logger::Loggable { diff --git a/test/java/io/envoyproxy/envoymobile/engine/AndroidNetworkMonitorTest.java b/test/java/io/envoyproxy/envoymobile/engine/AndroidNetworkMonitorTest.java new file mode 100644 index 0000000000..cf092882d4 --- /dev/null +++ b/test/java/io/envoyproxy/envoymobile/engine/AndroidNetworkMonitorTest.java @@ -0,0 +1,68 @@ +package io.envoyproxy.envoymobile.engine; + +import static org.robolectric.Shadows.shadowOf; + +import android.content.Context; +import android.content.Intent; +import android.Manifest; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import androidx.test.filters.MediumTest; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.rule.GrantPermissionRule; +import androidx.test.annotation.UiThreadTest; +import io.envoyproxy.envoymobile.MockEnvoyEngine; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.shadows.ShadowConnectivityManager; + +/** + * Tests functionality of AndroidNetworkMonitor + */ +@RunWith(RobolectricTestRunner.class) +public class AndroidNetworkMonitorTest { + + @Rule + public GrantPermissionRule mRuntimePermissionRule = + GrantPermissionRule.grant(Manifest.permission.ACCESS_NETWORK_STATE); + + private AndroidNetworkMonitor androidNetworkMonitor; + private ShadowConnectivityManager connectivityManager; + private Context context; + + @Before + public void setUp() { + context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + AndroidNetworkMonitor.load(context, new MockEnvoyEngine()); + androidNetworkMonitor = AndroidNetworkMonitor.getInstance(); + connectivityManager = shadowOf(androidNetworkMonitor.getConnectivityManager()); + } + + /** + * Tests that isOnline() returns the correct result. + */ + @Test + @MediumTest + @UiThreadTest + public void testAndroidNetworkMonitorIsOnline() { + Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); + // Set up network change + androidNetworkMonitor.onReceive(context, intent); + Assert.assertTrue(androidNetworkMonitor.isOnline()); + + // Save old networkInfo and simulate a no network scenerio + NetworkInfo networkInfo = androidNetworkMonitor.getConnectivityManager().getActiveNetworkInfo(); + connectivityManager.setActiveNetworkInfo(null); + androidNetworkMonitor.onReceive(context, intent); + Assert.assertFalse(androidNetworkMonitor.isOnline()); + + // Bring back online since the AndroidNetworkMonitor class is a singleton + connectivityManager.setActiveNetworkInfo(networkInfo); + androidNetworkMonitor.onReceive(context, intent); + } +} diff --git a/test/java/io/envoyproxy/envoymobile/engine/BUILD b/test/java/io/envoyproxy/envoymobile/engine/BUILD index bdd1fd2485..bd8b92011a 100644 --- a/test/java/io/envoyproxy/envoymobile/engine/BUILD +++ b/test/java/io/envoyproxy/envoymobile/engine/BUILD @@ -1,4 +1,4 @@ -load("@envoy_mobile//bazel:kotlin_test.bzl", "envoy_mobile_kt_test") +load("@envoy_mobile//bazel:kotlin_test.bzl", "envoy_mobile_android_test", "envoy_mobile_kt_test") licenses(["notice"]) # Apache 2 @@ -31,3 +31,19 @@ envoy_mobile_kt_test( "//library/java/io/envoyproxy/envoymobile/engine:envoy_base_engine_lib", ], ) + +envoy_mobile_android_test( + name = "android_network_monitor_tests", + srcs = [ + "AndroidNetworkMonitorTest.java", + ], + native_deps = [ + "//library/common/jni:libndk_envoy_jni.so", + "//library/common/jni:libndk_envoy_jni.jnilib", + ], + deps = [ + "//library/java/io/envoyproxy/envoymobile/engine:envoy_base_engine_lib", + "//library/java/io/envoyproxy/envoymobile/engine:envoy_engine_lib", + "//library/kotlin/io/envoyproxy/envoymobile:envoy_interfaces_lib", + ], +) diff --git a/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt b/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt index a55898f851..a50ee073c7 100644 --- a/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt +++ b/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt @@ -62,9 +62,6 @@ class EnvoyConfigurationTest { dnsQueryTimeoutSeconds: Int = 321, dnsMinRefreshSeconds: Int = 12, dnsPreresolveHostnames: String = "[hostname]", - dnsFallbackNameservers: List = emptyList(), - enableDnsFilterUnroutableFamilies: Boolean = true, - dnsUseSystemResolver: Boolean = true, enableDrainPostDnsRefresh: Boolean = false, enableHttp3: Boolean = false, enableGzip: Boolean = true, @@ -96,9 +93,6 @@ class EnvoyConfigurationTest { dnsQueryTimeoutSeconds, dnsMinRefreshSeconds, dnsPreresolveHostnames, - dnsFallbackNameservers, - enableDnsFilterUnroutableFamilies, - dnsUseSystemResolver, enableDrainPostDnsRefresh, enableHttp3, enableGzip, @@ -148,8 +142,6 @@ class EnvoyConfigurationTest { assertThat(resolvedTemplate).contains("&dns_multiple_addresses false") assertThat(resolvedTemplate).contains("&dns_min_refresh_rate 12s") assertThat(resolvedTemplate).contains("&dns_preresolve_hostnames [hostname]") - assertThat(resolvedTemplate).contains("&dns_resolver_name envoy.network.dns_resolver.getaddrinfo") - assertThat(resolvedTemplate).contains("&dns_resolver_config {\"@type\":\"type.googleapis.com/envoy.extensions.network.dns_resolver.getaddrinfo.v3.GetAddrInfoDnsResolverConfig\"}") assertThat(resolvedTemplate).contains("&enable_drain_post_dns_refresh false") // Interface Binding @@ -206,9 +198,6 @@ class EnvoyConfigurationTest { @Test fun `configuration resolves with alternate values`() { val envoyConfiguration = buildTestEnvoyConfiguration( - dnsFallbackNameservers = listOf("8.8.8.8"), - enableDnsFilterUnroutableFamilies = false, - dnsUseSystemResolver = false, enableDrainPostDnsRefresh = true, enableHappyEyeballs = true, enableHttp3 = true, @@ -226,7 +215,6 @@ CERT_VALIDATION_TEMPLATE ) // DNS - assertThat(resolvedTemplate).contains("&dns_resolver_config {\"@type\":\"type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig\",\"resolvers\":[{\"socket_address\":{\"address\":\"8.8.8.8\"}}],\"use_resolvers_as_fallback\": true, \"filter_unroutable_families\": false}") assertThat(resolvedTemplate).contains("&dns_lookup_family ALL") assertThat(resolvedTemplate).contains("&dns_multiple_addresses true") assertThat(resolvedTemplate).contains("&enable_drain_post_dns_refresh true") @@ -253,21 +241,6 @@ CERT_VALIDATION_TEMPLATE assertThat(resolvedTemplate).contains("&skip_dns_lookup_for_proxied_requests true") } - @Test - fun `configuration resolves with c ares DNS resolver`() { - val envoyConfiguration = buildTestEnvoyConfiguration( - dnsUseSystemResolver = false - ) - - val resolvedTemplate = envoyConfiguration.resolveTemplate( - TEST_CONFIG, PLATFORM_FILTER_CONFIG, NATIVE_FILTER_CONFIG, APCF_INSERT, GZIP_INSERT, BROTLI_INSERT, SOCKET_TAG_INSERT, - CERT_VALIDATION_TEMPLATE - ) - - assertThat(resolvedTemplate).contains("&dns_resolver_name envoy.network.dns_resolver.cares") - assertThat(resolvedTemplate).contains("&dns_resolver_config {\"@type\":\"type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig\",\"resolvers\":[],\"use_resolvers_as_fallback\": false, \"filter_unroutable_families\": true}") - } - @Test fun `resolve templates with invalid templates will throw on build`() { val envoyConfiguration = buildTestEnvoyConfiguration() @@ -279,19 +252,4 @@ CERT_VALIDATION_TEMPLATE assertThat(e.message).contains("missing") } } - - @Test - fun `resolving multiple dns fallback nameservers`() { - val envoyConfiguration = buildTestEnvoyConfiguration( - dnsFallbackNameservers = listOf("8.8.8.8", "1.1.1.1"), - dnsUseSystemResolver = false - ) - - val resolvedTemplate = envoyConfiguration.resolveTemplate( - TEST_CONFIG, PLATFORM_FILTER_CONFIG, NATIVE_FILTER_CONFIG, APCF_INSERT, GZIP_INSERT, BROTLI_INSERT, SOCKET_TAG_INSERT, -CERT_VALIDATION_TEMPLATE - ) - - assertThat(resolvedTemplate).contains("&dns_resolver_config {\"@type\":\"type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig\",\"resolvers\":[{\"socket_address\":{\"address\":\"8.8.8.8\"}},{\"socket_address\":{\"address\":\"1.1.1.1\"}}],\"use_resolvers_as_fallback\": true, \"filter_unroutable_families\": true}") - } } diff --git a/test/java/org/chromium/net/CronetUrlRequestTest.java b/test/java/org/chromium/net/CronetUrlRequestTest.java index 845f09e39d..abada86a53 100644 --- a/test/java/org/chromium/net/CronetUrlRequestTest.java +++ b/test/java/org/chromium/net/CronetUrlRequestTest.java @@ -8,12 +8,19 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.robolectric.Shadows.shadowOf; +import android.content.Context; +import android.content.Intent; +import android.Manifest; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; import android.os.Build; import android.os.ConditionVariable; import android.os.StrictMode; import android.util.Log; import androidx.test.filters.SmallTest; +import androidx.test.rule.GrantPermissionRule; import java.io.IOException; import java.net.ConnectException; import java.nio.ByteBuffer; @@ -28,6 +35,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.envoyproxy.envoymobile.engine.AndroidNetworkMonitor; import org.chromium.net.impl.CronetUrlRequest; import org.chromium.net.impl.Errors.EnvoyMobileError; import org.chromium.net.impl.Errors.NetError; @@ -49,8 +57,10 @@ import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; +import org.robolectric.shadows.ShadowConnectivityManager; /** * Test functionality of CronetUrlRequest. @@ -64,26 +74,25 @@ public class CronetUrlRequestTest { private static final String REFER_STRING = "refer"; private static final String REFERRER_HEADER_NAME = REFER_STRING + "er"; - @Rule public final CronetTestRule mTestRule = new CronetTestRule(); + private final CronetTestRule mTestRule = new CronetTestRule(); + private final GrantPermissionRule mRuntimePermissionRule = + GrantPermissionRule.grant(Manifest.permission.ACCESS_NETWORK_STATE); + @Rule + public final RuleChain chain = RuleChain.outerRule(mTestRule).around(mRuntimePermissionRule); private CronetTestFramework mTestFramework; private MockUrlRequestJobFactory mMockUrlRequestJobFactory; @Before public void setUp() { - mTestFramework = mTestRule.startCronetTestFramework(); + mMockUrlRequestJobFactory = new MockUrlRequestJobFactory( + mTestRule.buildCronetTestFramework().mBuilder, mTestRule.testingJavaImpl()); assertTrue(NativeTestServer.startNativeTestServer(getContext())); - // Add url interceptors after native application context is initialized. - if (!mTestRule.testingJavaImpl()) { - mMockUrlRequestJobFactory = new MockUrlRequestJobFactory(mTestFramework.mBuilder); - } } @After public void tearDown() { - if (!mTestRule.testingJavaImpl()) { - mMockUrlRequestJobFactory.shutdown(); - } + mMockUrlRequestJobFactory.shutdown(); NativeTestServer.shutdownNativeTestServer(); } @@ -126,28 +135,29 @@ private void checkResponseInfoHeader(UrlResponseInfo responseInfo, String header public void testBuilderChecks() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); try { - mTestFramework.mCronetEngine.newUrlRequestBuilder(null, callback, callback.getExecutor()); + mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder(null, callback, + callback.getExecutor()); fail("URL not null-checked"); } catch (NullPointerException e) { assertEquals("URL is required.", e.getMessage()); } try { - mTestFramework.mCronetEngine.newUrlRequestBuilder(NativeTestServer.getRedirectURL(), null, - callback.getExecutor()); + mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( + NativeTestServer.getRedirectURL(), null, callback.getExecutor()); fail("Callback not null-checked"); } catch (NullPointerException e) { assertEquals("Callback is required.", e.getMessage()); } try { - mTestFramework.mCronetEngine.newUrlRequestBuilder(NativeTestServer.getRedirectURL(), callback, - null); + mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( + NativeTestServer.getRedirectURL(), callback, null); fail("Executor not null-checked"); } catch (NullPointerException e) { assertEquals("Executor is required.", e.getMessage()); } // Verify successful creation doesn't throw. - mTestFramework.mCronetEngine.newUrlRequestBuilder(NativeTestServer.getRedirectURL(), callback, - callback.getExecutor()); + mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( + NativeTestServer.getRedirectURL(), callback, callback.getExecutor()); } @Test @@ -155,7 +165,8 @@ public void testBuilderChecks() throws Exception { @Feature({"Cronet"}) public void testSimpleGet() throws Exception { String url = NativeTestServer.getEchoMethodURL(); - TestUrlRequestCallback callback = startAndWaitForComplete(mTestFramework.mCronetEngine, url); + TestUrlRequestCallback callback = + startAndWaitForComplete(mMockUrlRequestJobFactory.getCronetEngine(), url); assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); // Default method is 'GET'. assertEquals("GET", callback.mResponseAsString); @@ -204,7 +215,7 @@ public void testRedirectAsync() throws Exception { // Start the request and wait to see the redirect. TestUrlRequestCallback callback = new TestUrlRequestCallback(); callback.setAutoAdvance(false); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getRedirectURL(), callback, callback.getExecutor()); UrlRequest urlRequest = builder.build(); urlRequest.start(); @@ -290,8 +301,8 @@ public void testRedirectWithNullLocationHeader() throws Exception { String url = NativeTestServer.getFileURL("/redirect_broken_header.html"); TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = - mTestFramework.mCronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor()); + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( + url, callback, callback.getExecutor()); final UrlRequest urlRequest = builder.build(); urlRequest.start(); callback.blockForDone(); @@ -355,7 +366,7 @@ public void onCanceled(UrlRequest request, UrlResponseInfo info) { } }; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getMultiRedirectURL(), callback, callback.getExecutor()); final UrlRequest urlRequest = builder.build(); @@ -373,7 +384,8 @@ public void onCanceled(UrlRequest request, UrlResponseInfo info) { @Feature({"Cronet"}) public void testNotFound() throws Exception { String url = NativeTestServer.getFileURL("/notfound.html"); - TestUrlRequestCallback callback = startAndWaitForComplete(mTestFramework.mCronetEngine, url); + TestUrlRequestCallback callback = + startAndWaitForComplete(mMockUrlRequestJobFactory.getCronetEngine(), url); checkResponseInfo(callback.mResponseInfo, url, 404, "Not Found"); assertEquals("\n\n\nNot found\n" + "

Test page loaded.

\n\n\n", @@ -392,7 +404,8 @@ public void testNotFound() throws Exception { @Ignore("https://github.com/envoyproxy/envoy-mobile/issues/1550") public void testContentLengthMismatchFailsOnce() throws Exception { String url = NativeTestServer.getFileURL("/content_length_mismatch.html"); - TestUrlRequestCallback callback = startAndWaitForComplete(mTestFramework.mCronetEngine, url); + TestUrlRequestCallback callback = + startAndWaitForComplete(mMockUrlRequestJobFactory.getCronetEngine(), url); assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); // The entire response body will be read before the error is returned. // This is because the network stack returns data as it's read from the @@ -414,7 +427,7 @@ public void testContentLengthMismatchFailsOnce() throws Exception { public void testSetHttpMethod() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); String methodName = "HEAD"; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoMethodURL(), callback, callback.getExecutor()); // Try to set 'null' method. try { @@ -436,7 +449,7 @@ public void testSetHttpMethod() throws Exception { @Feature({"Cronet"}) public void testBadMethod() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( TEST_URL, callback, callback.getExecutor()); try { builder.setHttpMethod("bad:method!"); @@ -452,7 +465,7 @@ public void testBadMethod() throws Exception { @Feature({"Cronet"}) public void testBadHeaderName() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( TEST_URL, callback, callback.getExecutor()); try { builder.addHeader("header:name", "headervalue"); @@ -468,7 +481,7 @@ public void testBadHeaderName() throws Exception { @Feature({"Cronet"}) public void testAcceptEncodingIgnored() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoAllHeadersURL(), callback, callback.getExecutor()); // This line should eventually throw an exception, once callers have migrated builder.addHeader("accept-encoding", "foozip"); @@ -482,7 +495,7 @@ public void testAcceptEncodingIgnored() throws Exception { @Feature({"Cronet"}) public void testBadHeaderValue() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( TEST_URL, callback, callback.getExecutor()); try { builder.addHeader("headername", "bad header\r\nvalue"); @@ -500,7 +513,7 @@ public void testAddHeader() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); String headerName = "header-name"; String headerValue = "header-value"; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoHeaderURL(headerName), callback, callback.getExecutor()); builder.addHeader(headerName, headerValue); @@ -519,7 +532,7 @@ public void testMultiRequestHeaders() throws Exception { String headerName = "header-name"; String headerValue1 = "header-value1"; String headerValue2 = "header-value2"; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoAllHeadersURL(), callback, callback.getExecutor()); builder.addHeader(headerName, headerValue1); builder.addHeader(headerName, headerValue2); @@ -543,7 +556,7 @@ public void testMultiRequestHeaders() throws Exception { public void testCustomReferer_verbatim() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); String refererValue = "http://example.com/"; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoHeaderURL(REFERRER_HEADER_NAME), callback, callback.getExecutor()); builder.addHeader(REFERRER_HEADER_NAME, refererValue); builder.build().start(); @@ -560,7 +573,7 @@ public void testCustomReferer_verbatim() throws Exception { public void testCustomReferer_changeToCanonical() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); String refererValueNoTrailingSlash = "http://example.com"; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoHeaderURL(REFERRER_HEADER_NAME), callback, callback.getExecutor()); builder.addHeader(REFERRER_HEADER_NAME, refererValueNoTrailingSlash); builder.build().start(); @@ -577,7 +590,7 @@ public void testCustomReferer_changeToCanonical() throws Exception { public void testCustomReferer_discardInvalid() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); String invalidRefererValue = "foobar"; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoHeaderURL(REFERRER_HEADER_NAME), callback, callback.getExecutor()); builder.addHeader(REFERRER_HEADER_NAME, invalidRefererValue); builder.build().start(); @@ -593,7 +606,7 @@ public void testCustomUserAgent() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); String userAgentName = "user-agent"; String userAgentValue = "User-Agent-Value"; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoHeaderURL(userAgentName), callback, callback.getExecutor()); builder.addHeader(userAgentName, userAgentValue); builder.build().start(); @@ -608,7 +621,7 @@ public void testCustomUserAgent() throws Exception { public void testDefaultUserAgent() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); String headerName = "user-agent"; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoHeaderURL(headerName), callback, callback.getExecutor()); builder.build().start(); callback.blockForDone(); @@ -622,8 +635,8 @@ public void testDefaultUserAgent() throws Exception { @SmallTest @Feature({"Cronet"}) public void testMockSuccess() throws Exception { - TestUrlRequestCallback callback = - startAndWaitForComplete(mTestFramework.mCronetEngine, NativeTestServer.getSuccessURL()); + TestUrlRequestCallback callback = startAndWaitForComplete( + mMockUrlRequestJobFactory.getCronetEngine(), NativeTestServer.getSuccessURL()); assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); assertEquals(0, callback.mRedirectResponseInfoList.size()); assertTrue(callback.mHttpResponseDataLength != 0); @@ -640,8 +653,8 @@ public void testMockSuccess() throws Exception { @SmallTest @Feature({"Cronet"}) public void testResponseHeadersList() throws Exception { - TestUrlRequestCallback callback = - startAndWaitForComplete(mTestFramework.mCronetEngine, NativeTestServer.getSuccessURL()); + TestUrlRequestCallback callback = startAndWaitForComplete( + mMockUrlRequestJobFactory.getCronetEngine(), NativeTestServer.getSuccessURL()); assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); List> responseHeaders = callback.mResponseInfo.getAllHeadersAsList(); @@ -663,7 +676,7 @@ public void testResponseHeadersList() throws Exception { @Feature({"Cronet"}) public void testMockMultiRedirect() throws Exception { TestUrlRequestCallback callback = startAndWaitForComplete( - mTestFramework.mCronetEngine, NativeTestServer.getMultiRedirectURL()); + mMockUrlRequestJobFactory.getCronetEngine(), NativeTestServer.getMultiRedirectURL()); UrlResponseInfo mResponseInfo = callback.mResponseInfo; assertEquals(2, callback.mRedirectCount); assertEquals(200, mResponseInfo.getHttpStatusCode()); @@ -696,8 +709,8 @@ public void testMockMultiRedirect() throws Exception { @SmallTest @Feature({"Cronet"}) public void testMockNotFound() throws Exception { - TestUrlRequestCallback callback = - startAndWaitForComplete(mTestFramework.mCronetEngine, NativeTestServer.getNotFoundURL()); + TestUrlRequestCallback callback = startAndWaitForComplete( + mMockUrlRequestJobFactory.getCronetEngine(), NativeTestServer.getNotFoundURL()); UrlResponseInfo expected = createUrlResponseInfo(new String[] {NativeTestServer.getNotFoundURL()}, "Not Found", 404, 142, "Content-Length", "96"); @@ -810,7 +823,7 @@ public void testSimpleGetBufferUpdates() throws Exception { callback.setAutoAdvance(false); // Since the default method is "GET", the expected response body is also // "GET". - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoMethodURL(), callback, callback.getExecutor()); UrlRequest urlRequest = builder.build(); urlRequest.start(); @@ -893,7 +906,7 @@ public void testSimpleGetBufferUpdates() throws Exception { public void testBadBuffers() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); callback.setAutoAdvance(false); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoMethodURL(), callback, callback.getExecutor()); UrlRequest urlRequest = builder.build(); urlRequest.start(); @@ -934,7 +947,7 @@ public void testNoIoInCancel() throws Exception { final TestUrlRequestCallback callback = new TestUrlRequestCallback(); callback.setAutoAdvance(false); final UrlRequest urlRequest = - mTestFramework.mCronetEngine + mMockUrlRequestJobFactory.getCronetEngine() .newUrlRequestBuilder(NativeTestServer.getEchoHeaderURL("blah-header"), callback, callback.getExecutor()) .addHeader("blah-header", "blahblahblah") @@ -961,7 +974,7 @@ public void testNoIoInCancel() throws Exception { public void testUnexpectedReads() throws Exception { final TestUrlRequestCallback callback = new TestUrlRequestCallback(); callback.setAutoAdvance(false); - final UrlRequest urlRequest = mTestFramework.mCronetEngine + final UrlRequest urlRequest = mMockUrlRequestJobFactory.getCronetEngine() .newUrlRequestBuilder(NativeTestServer.getRedirectURL(), callback, callback.getExecutor()) .build(); @@ -1037,7 +1050,7 @@ public void run() { public void testUnexpectedFollowRedirects() throws Exception { final TestUrlRequestCallback callback = new TestUrlRequestCallback(); callback.setAutoAdvance(false); - final UrlRequest urlRequest = mTestFramework.mCronetEngine + final UrlRequest urlRequest = mMockUrlRequestJobFactory.getCronetEngine() .newUrlRequestBuilder(NativeTestServer.getRedirectURL(), callback, callback.getExecutor()) .build(); @@ -1110,7 +1123,7 @@ public void run() { @Feature({"Cronet"}) public void testUploadSetDataProvider() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); try { @@ -1135,7 +1148,7 @@ public void testUploadSetDataProvider() throws Exception { @Feature({"Cronet"}) public void testUploadEmptyBodySync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1159,7 +1172,7 @@ public void testUploadEmptyBodySync() throws Exception { @Feature({"Cronet"}) public void testUploadSync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1184,7 +1197,7 @@ public void testUploadSync() throws Exception { @Feature({"Cronet"}) public void testUploadMultiplePiecesSync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1213,7 +1226,7 @@ public void testUploadMultiplePiecesSync() throws Exception { @Feature({"Cronet"}) public void testUploadMultiplePiecesAsync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1242,7 +1255,7 @@ public void testUploadMultiplePiecesAsync() throws Exception { @Feature({"Cronet"}) public void testUploadChangesDefaultMethod() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoMethodURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1263,7 +1276,7 @@ public void testUploadChangesDefaultMethod() throws Exception { @Feature({"Cronet"}) public void testUploadWithSetMethod() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoMethodURL(), callback, callback.getExecutor()); final String method = "PUT"; @@ -1287,7 +1300,7 @@ public void testUploadWithSetMethod() throws Exception { @Feature({"Cronet"}) public void testUploadRedirectSync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getRedirectToEchoBody(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1312,7 +1325,7 @@ public void testUploadRedirectSync() throws Exception { @Feature({"Cronet"}) public void testUploadRedirectAsync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getRedirectToEchoBody(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1337,7 +1350,7 @@ public void testUploadRedirectAsync() throws Exception { @Feature({"Cronet"}) public void testUploadWithBadLength() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1370,7 +1383,7 @@ public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) throws IO @Feature({"Cronet"}) public void testUploadWithBadLengthBufferAligned() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1402,7 +1415,7 @@ public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) throws IO @Feature({"Cronet"}) public void testUploadReadFailSync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1430,7 +1443,7 @@ public void testUploadReadFailSync() throws Exception { @Feature({"Cronet"}) public void testUploadLengthFailSync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1458,7 +1471,7 @@ public void testUploadLengthFailSync() throws Exception { @Feature({"Cronet"}) public void testUploadReadFailAsync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1493,7 +1506,7 @@ public void execute(Runnable command) { command.run(); } }; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = @@ -1527,7 +1540,7 @@ public void execute(Runnable command) { command.run(); } }; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, myExecutor); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1562,7 +1575,7 @@ public void execute(Runnable command) { command.run(); } }; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, myExecutor); UploadDataProvider dataProvider = UploadDataProviders.create("test".getBytes()); builder.setUploadDataProvider(dataProvider, myExecutor); @@ -1584,7 +1597,7 @@ public void execute(Runnable command) { @Feature({"Cronet"}) public void testUploadReadFailThrown() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1612,7 +1625,7 @@ public void testUploadReadFailThrown() throws Exception { @Feature({"Cronet"}) public void testUploadRewindFailSync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getRedirectToEchoBody(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1638,7 +1651,7 @@ public void testUploadRewindFailSync() throws Exception { @Feature({"Cronet"}) public void testUploadRewindFailAsync() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getRedirectToEchoBody(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1664,7 +1677,7 @@ public void testUploadRewindFailAsync() throws Exception { @Feature({"Cronet"}) public void testUploadRewindFailThrown() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getRedirectToEchoBody(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1690,7 +1703,7 @@ public void testUploadRewindFailThrown() throws Exception { @Feature({"Cronet"}) public void testUploadChunked() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1716,7 +1729,7 @@ public void testUploadChunked() throws Exception { @Feature({"Cronet"}) public void testUploadChunkedLastReadZeroLengthBody() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1749,7 +1762,7 @@ public void testUploadChunkedLastReadZeroLengthBody() throws Exception { public void testUploadFailsWithoutInitializingStream() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); // The port for PTP will always refuse a TCP connection - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( "http://127.0.0.1:319", callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -1778,7 +1791,7 @@ private void throwOrCancel(FailureType failureType, ResponseStep failureStep, } TestUrlRequestCallback callback = new TestUrlRequestCallback(); callback.setFailure(failureType, failureStep); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getRedirectURL(), callback, callback.getExecutor()); UrlRequest urlRequest = builder.build(); urlRequest.start(); @@ -1839,7 +1852,7 @@ public void testThrowOrCancelInOnSucceeded() { for (FailureType type : testTypes) { TestUrlRequestCallback callback = new TestUrlRequestCallback(); callback.setFailure(type, ResponseStep.ON_SUCCEEDED); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoMethodURL(), callback, callback.getExecutor()); UrlRequest urlRequest = builder.build(); urlRequest.start(); @@ -1868,8 +1881,8 @@ public void testThrowOrCancelInOnFailed() { NativeTestServer.shutdownNativeTestServer(); TestUrlRequestCallback callback = new TestUrlRequestCallback(); callback.setFailure(type, ResponseStep.ON_FAILED); - UrlRequest.Builder builder = - mTestFramework.mCronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor()); + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( + url, callback, callback.getExecutor()); UrlRequest urlRequest = builder.build(); urlRequest.start(); callback.blockForDone(); @@ -1899,7 +1912,7 @@ public void onResponseStarted(UrlRequest request, UrlResponseInfo info) { } }; callback.setFailure(type, ResponseStep.ON_CANCELED); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); UrlRequest urlRequest = builder.build(); urlRequest.start(); @@ -1923,7 +1936,7 @@ public void testExecutorShutdown() { TestUrlRequestCallback callback = new TestUrlRequestCallback(); callback.setAutoAdvance(false); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); CronetUrlRequest urlRequest = (CronetUrlRequest)builder.build(); urlRequest.start(); @@ -1977,7 +1990,7 @@ public void rewind(final UploadDataSink uploadDataSink) {} } TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); ExecutorService uploadExecutor = Executors.newSingleThreadExecutor(); @@ -2021,7 +2034,7 @@ public void onSucceeded(UrlRequest request, UrlResponseInfo info) { @Ignore("Not yet implemented") public void testDestroyUploadDataStreamAdapterOnSucceededCallback() throws Exception { TestUrlRequestCallback callback = new QuitOnSuccessCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getEchoBodyURL(), callback, callback.getExecutor()); TestUploadDataProvider dataProvider = new TestUploadDataProvider( @@ -2068,10 +2081,35 @@ public void testErrorCodes() throws Exception { NetworkException.ERROR_TIMED_OUT, "TIMED_OUT", true); checkSpecificErrorCode(0x2000, NetError.ERR_OTHER, NetworkException.ERROR_OTHER, "OTHER", false); - // Todo(colibie): https://github.com/envoyproxy/envoy-mobile/issues/1549 - // checkSpecificErrorCode(-106, NetworkException.ERROR_INTERNET_DISCONNECTED, - // "INTERNET_DISCONNECTED", false); - // checkSpecificErrorCode(-21, NetworkException.ERROR_NETWORK_CHANGED, "NETWORK_CHANGED", true); + } + + /* + * Verifies INTERNET_DISCONNECTED error is thrown when no network + */ + @Test + @SmallTest + @Feature({"Cronet"}) + @OnlyRunNativeCronet // Java impl doesn't support MockUrlRequestJobFactory + public void testInternetDisconnectedError() throws Exception { + AndroidNetworkMonitor androidNetworkMonitor = AndroidNetworkMonitor.getInstance(); + Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); + // save old networkInfo before overriding + NetworkInfo networkInfo = androidNetworkMonitor.getConnectivityManager().getActiveNetworkInfo(); + + // simulate no network + ShadowConnectivityManager connectivityManager = + shadowOf(androidNetworkMonitor.getConnectivityManager()); + connectivityManager.setActiveNetworkInfo(null); + androidNetworkMonitor.onReceive(getContext(), intent); + + // send request and confirm errorcode + checkSpecificErrorCode( + EnvoyMobileError.DNS_RESOLUTION_FAILED, NetError.ERR_INTERNET_DISCONNECTED, + NetworkException.ERROR_INTERNET_DISCONNECTED, "INTERNET_DISCONNECTED", false); + + // bring back online since the AndroidNetworkMonitor class is a singleton + connectivityManager.setActiveNetworkInfo(networkInfo); + androidNetworkMonitor.onReceive(getContext(), intent); } /* @@ -2083,14 +2121,16 @@ public void testErrorCodes() throws Exception { public void testCookiesArentSavedOrSent() throws Exception { // Make a request to a url that sets the cookie String url = NativeTestServer.getFileURL("/set_cookie.html"); - TestUrlRequestCallback callback = startAndWaitForComplete(mTestFramework.mCronetEngine, url); + TestUrlRequestCallback callback = + startAndWaitForComplete(mMockUrlRequestJobFactory.getCronetEngine(), url); assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); assertEquals("A=B", callback.mResponseInfo.getAllHeaders().get("Set-Cookie").get(0)); // Make a request that check that cookie header isn't sent. String headerName = "Cookie"; String url2 = NativeTestServer.getEchoHeaderURL(headerName); - TestUrlRequestCallback callback2 = startAndWaitForComplete(mTestFramework.mCronetEngine, url2); + TestUrlRequestCallback callback2 = + startAndWaitForComplete(mMockUrlRequestJobFactory.getCronetEngine(), url2); assertEquals(200, callback2.mResponseInfo.getHttpStatusCode()); assertEquals("Header not found. :(", callback2.mResponseAsString); } @@ -2099,12 +2139,11 @@ public void testCookiesArentSavedOrSent() throws Exception { @SmallTest @Feature({"Cronet"}) @OnlyRunNativeCronet - @Ignore("https://github.com/envoyproxy/envoy-mobile/issues/1549") public void testQuicErrorCode() throws Exception { + long envoyMobileError = 0x2000; TestUrlRequestCallback callback = startAndWaitForComplete( mMockUrlRequestJobFactory.getCronetEngine(), - MockUrlRequestJobFactory.getMockUrlWithFailure( - FailurePhase.START, NetError.ERR_QUIC_PROTOCOL_ERROR.getErrorCode())); + MockUrlRequestJobFactory.getMockQuicUrlWithFailure(envoyMobileError)); assertNull(callback.mResponseInfo); assertNotNull(callback.mError); assertEquals(NetworkException.ERROR_QUIC_PROTOCOL_FAILED, @@ -2115,28 +2154,6 @@ public void testQuicErrorCode() throws Exception { assertEquals(1, quicException.getQuicDetailedErrorCode()); } - @Test - @SmallTest - @Feature({"Cronet"}) - @OnlyRunNativeCronet - @Ignore("https://github.com/envoyproxy/envoy-mobile/issues/1549") - public void testQuicErrorCodeForNetworkChanged() throws Exception { - TestUrlRequestCallback callback = startAndWaitForComplete( - mMockUrlRequestJobFactory.getCronetEngine(), - MockUrlRequestJobFactory.getMockUrlWithFailure( - FailurePhase.START, NetError.ERR_NETWORK_CHANGED.getErrorCode())); - assertNull(callback.mResponseInfo); - assertNotNull(callback.mError); - assertEquals(NetworkException.ERROR_NETWORK_CHANGED, - ((NetworkException)callback.mError).getErrorCode()); - assertTrue(callback.mError instanceof QuicException); - QuicException quicException = (QuicException)callback.mError; - // QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK(83) is set in - // URLRequestFailedJob::PopulateNetErrorDetails for this test. - final int quicErrorCode = 83; - assertEquals(quicErrorCode, quicException.getQuicDetailedErrorCode()); - } - /** * Tests that legacy onFailed callback is invoked with UrlRequestException if there * is no onFailed callback implementation that takes CronetException. @@ -2145,9 +2162,9 @@ public void testQuicErrorCodeForNetworkChanged() throws Exception { @SmallTest @Feature({"Cronet"}) @OnlyRunNativeCronet - @Ignore("https://github.com/envoyproxy/envoy-mobile/issues/1549") public void testLegacyOnFailedCallback() throws Exception { - final int netError = -123; + final long envoyMobileError = 0x2000; + final int netError = NetError.ERR_OTHER.getErrorCode(); final AtomicBoolean failedExpectation = new AtomicBoolean(); final ConditionVariable done = new ConditionVariable(); UrlRequest.Callback callback = new UrlRequest.Callback() { @@ -2191,8 +2208,8 @@ public void onCanceled(UrlRequest request, UrlResponseInfo info) { } }; - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( - MockUrlRequestJobFactory.getMockUrlWithFailure(FailurePhase.START, netError), callback, + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( + MockUrlRequestJobFactory.getMockUrlWithFailure(envoyMobileError), callback, Executors.newSingleThreadExecutor()); final UrlRequest urlRequest = builder.build(); urlRequest.start(); @@ -2204,9 +2221,9 @@ public void onCanceled(UrlRequest request, UrlResponseInfo info) { private void checkSpecificErrorCode(@EnvoyMobileError long envoyMobileError, NetError netError, int errorCode, String name, boolean immediatelyRetryable) throws Exception { - TestUrlRequestCallback callback = startAndWaitForComplete( - mMockUrlRequestJobFactory.getCronetEngine(), - MockUrlRequestJobFactory.getMockUrlWithFailure(FailurePhase.START, envoyMobileError)); + TestUrlRequestCallback callback = + startAndWaitForComplete(mMockUrlRequestJobFactory.getCronetEngine(), + MockUrlRequestJobFactory.getMockUrlWithFailure(envoyMobileError)); assertNull(callback.mResponseInfo); assertNotNull(callback.mError); assertEquals(netError.getErrorCode(), @@ -2252,7 +2269,8 @@ public void testCleartextTrafficBlocked() throws Exception { // https requests to it are tested in QuicTest, so this checks that we're only blocking // cleartext. final String url = "http://example.com/simple.txt"; - TestUrlRequestCallback callback = startAndWaitForComplete(mTestFramework.mCronetEngine, url); + TestUrlRequestCallback callback = + startAndWaitForComplete(mMockUrlRequestJobFactory.getCronetEngine(), url); assertNull(callback.mResponseInfo); assertNotNull(callback.mError); assertEquals(cleartextNotPermitted, @@ -2272,9 +2290,9 @@ public void testGzipCancel() throws Exception { for (int i = 0; i < 100; i++) { TestUrlRequestCallback callback = new TestUrlRequestCallback(); callback.setAutoAdvance(false); - UrlRequest urlRequest = - mTestFramework.mCronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor()) - .build(); + UrlRequest urlRequest = mMockUrlRequestJobFactory.getCronetEngine() + .newUrlRequestBuilder(url, callback, callback.getExecutor()) + .build(); urlRequest.start(); urlRequest.cancel(); // If the test blocks until each UrlRequest finishes before starting the next UrlRequest @@ -2302,7 +2320,7 @@ public void testGzipCancel() throws Exception { /** Do a HEAD request and get back a 404. */ public void test404Head() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( NativeTestServer.getFileURL("/notfound.html"), callback, callback.getExecutor()); builder.setHttpMethod("HEAD").build().start(); callback.blockForDone(); @@ -2334,7 +2352,7 @@ public void testManyRequests() throws Exception { } else { callbacks[i] = new TestUrlRequestCallback(callbacks[0].getExecutor()); } - UrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( + UrlRequest.Builder builder = mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( url, callbacks[i], callbacks[i].getExecutor()); requests[i] = builder.build(); } @@ -2354,8 +2372,9 @@ public void testManyRequests() throws Exception { @Feature({"Cronet"}) public void testSetIdempotency() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); - ExperimentalUrlRequest.Builder builder = mTestFramework.mCronetEngine.newUrlRequestBuilder( - NativeTestServer.getEchoMethodURL(), callback, callback.getExecutor()); + ExperimentalUrlRequest.Builder builder = + mMockUrlRequestJobFactory.getCronetEngine().newUrlRequestBuilder( + NativeTestServer.getEchoMethodURL(), callback, callback.getExecutor()); assertEquals(builder.setIdempotency(ExperimentalUrlRequest.Builder.IDEMPOTENT), builder); TestUploadDataProvider dataProvider = new TestUploadDataProvider( diff --git a/test/java/org/chromium/net/testing/CronetTestRule.java b/test/java/org/chromium/net/testing/CronetTestRule.java index 533e7c7638..6764f29078 100644 --- a/test/java/org/chromium/net/testing/CronetTestRule.java +++ b/test/java/org/chromium/net/testing/CronetTestRule.java @@ -264,7 +264,7 @@ private void setUp() { private void tearDown() { if (mCronetTestFramework != null) { - mCronetTestFramework.mCronetEngine.shutdown(); + mCronetTestFramework.shutdownEngine(); mCronetTestFramework = null; } diff --git a/test/java/org/chromium/net/testing/MockUrlRequestJobFactory.java b/test/java/org/chromium/net/testing/MockUrlRequestJobFactory.java index 6c6393e587..eaf9a3cda3 100644 --- a/test/java/org/chromium/net/testing/MockUrlRequestJobFactory.java +++ b/test/java/org/chromium/net/testing/MockUrlRequestJobFactory.java @@ -6,7 +6,7 @@ import org.chromium.net.ExperimentalCronetEngine; /** - * Helper class to set up url interceptors for testing purposes. + * Helper class to set up request filters for testing purposes. * TODO("https://github.com/envoyproxy/envoy-mobile/issues/1549") */ public final class MockUrlRequestJobFactory { @@ -18,19 +18,22 @@ public final class MockUrlRequestJobFactory { /** * Sets up URL interceptors. */ - public MockUrlRequestJobFactory(CronetEngine cronetEngine) { - mCronetEngine = cronetEngine; - - // Add a filter to immediately return a response - } + public MockUrlRequestJobFactory(CronetEngine cronetEngine) { mCronetEngine = cronetEngine; } /** - * Sets up URL interceptors. + * Sets up request filters. + * This optionally adds a request filter to the cronetEngine before building. + * JavaCronetEngine does not support these filters. */ - public MockUrlRequestJobFactory(ExperimentalCronetEngine.Builder builder) { - // Add a filter to immediately return a response - mCronetEngine = - CronetTestUtil.getCronetEngineBuilderImpl(builder).addUrlInterceptorsForTesting().build(); + public MockUrlRequestJobFactory(ExperimentalCronetEngine.Builder builder, + boolean testingJavaImpl) { + if (testingJavaImpl) { + mCronetEngine = builder.build(); + } else { + // Add a filter to immediately return a response + mCronetEngine = + CronetTestUtil.getCronetEngineBuilderImpl(builder).addUrlInterceptorsForTesting().build(); + } } /** @@ -41,7 +44,9 @@ public void shutdown() { mCronetEngine.shutdown(); } - public CronetEngine getCronetEngine() { return mCronetEngine; } + public ExperimentalCronetEngine getCronetEngine() { + return (ExperimentalCronetEngine)mCronetEngine; + } /** * Constructs a mock URL that hangs or fails at certain phase. @@ -50,20 +55,16 @@ public void shutdown() { * org.chromium.net.test.FailurePhase. * @param @param envoyMobileError reported by the engine. */ - public static String getMockUrlWithFailure(FailurePhase phase, long envoyMobileError) { - switch (phase) { - case START: - case READ_SYNC: - case READ_ASYNC: - break; - default: - throw new IllegalArgumentException("phase not in org.chromium.net.test.FailurePhase"); - } - return TEST_URL + "/failed?" + phase + "=" + envoyMobileError; + public static String getMockUrlWithFailure(long envoyMobileError) { + return TEST_URL + "/failed?error=" + envoyMobileError; + } + + public static String getMockQuicUrlWithFailure(long envoyMobileError) { + return TEST_URL + "/failed?quic=1&error=" + envoyMobileError; } public static String getMockUrlWithFailure(FailurePhase phase, int netError) { - throw new UnsupportedOperationException("To be implemented"); + throw new UnsupportedOperationException("To be implemented or deleted"); } /** diff --git a/test/kotlin/apps/experimental/MainActivity.kt b/test/kotlin/apps/experimental/MainActivity.kt index 2fdd401e49..0930124b01 100644 --- a/test/kotlin/apps/experimental/MainActivity.kt +++ b/test/kotlin/apps/experimental/MainActivity.kt @@ -58,7 +58,6 @@ class MainActivity : Activity() { .h2ExtendKeepaliveTimeout(true) .enableAdminInterface() .enableInterfaceBinding(true) - .enableDNSUseSystemResolver(false) .enableSocketTagging(true) .enableProxying(true) .enableSkipDNSLookupForProxiedRequests(true) diff --git a/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt b/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt index 4a83412e9c..b363328dff 100644 --- a/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt +++ b/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt @@ -110,26 +110,6 @@ class EngineBuilderTest { assertThat(engine.envoyConfiguration.dnsQueryTimeoutSeconds).isEqualTo(1234) } - @Test - fun `specifying dns fallback nameservers overrides default`() { - engineBuilder = EngineBuilder(Standard()) - engineBuilder.addEngineType { envoyEngine } - engineBuilder.addDNSFallbackNameservers(listOf("8.8.8.8")) - - val engine = engineBuilder.build() as EngineImpl - assertThat(engine.envoyConfiguration.dnsFallbackNameservers.size).isEqualTo(1) - } - - @Test - fun `specifying dns filter unroutable families overrides default`() { - engineBuilder = EngineBuilder(Standard()) - engineBuilder.addEngineType { envoyEngine } - engineBuilder.enableDNSFilterUnroutableFamilies(true) - - val engine = engineBuilder.build() as EngineImpl - assertThat(engine.envoyConfiguration.dnsFilterUnroutableFamilies).isTrue() - } - @Test fun `specifying H2 Ping idle interval overrides default`() { engineBuilder = EngineBuilder(Standard()) diff --git a/test/python/BUILD b/test/python/BUILD index 00ae8edf0f..4e06a4a9e7 100644 --- a/test/python/BUILD +++ b/test/python/BUILD @@ -1,4 +1,4 @@ -load("@pip//:requirements.bzl", "requirement") +load("@mobile_pip3//:requirements.bzl", "requirement") load("@rules_python//python:defs.bzl", "py_test") licenses(["notice"]) # Apache 2 diff --git a/test/python/benchmark/envoy_vs_requests.py b/test/python/benchmark/envoy_vs_requests.py index 5961aa7a65..b291d10499 100644 --- a/test/python/benchmark/envoy_vs_requests.py +++ b/test/python/benchmark/envoy_vs_requests.py @@ -1,4 +1,5 @@ import gevent.monkey + gevent.monkey.patch_all() import gevent @@ -8,7 +9,6 @@ from library.python.envoy_requests import gevent as envoy_requests - envoy_requests.pre_build_engine() diff --git a/test/python/echo_server.py b/test/python/echo_server.py index f3d048d0dd..4603a38c3e 100644 --- a/test/python/echo_server.py +++ b/test/python/echo_server.py @@ -4,6 +4,7 @@ class EchoServerHandler(BaseHTTPRequestHandler): + def do_GET(self): self._serve_echo() @@ -42,7 +43,8 @@ def _serve_echo(self): request_data = { "body": body, - "headers": {key: self.headers[key] for key in self.headers.keys()}, + "headers": {key: self.headers[key] + for key in self.headers.keys()}, "method": self.command, "path": self.path, } diff --git a/test/python/integration/test_send_headers.py b/test/python/integration/test_send_headers.py index 401aceb43e..9e3177ff60 100644 --- a/test/python/integration/test_send_headers.py +++ b/test/python/integration/test_send_headers.py @@ -1,7 +1,6 @@ from library.python.envoy_requests.common.engine import Engine from library.python.envoy_requests import get - API_LISTENER_TYPE = "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.EnvoyMobileHttpConnectionManager" ASSERTION_FILTER_TYPE = "type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion" diff --git a/test/python/runner.py b/test/python/runner.py index 1766ce1ab4..8204f708ab 100644 --- a/test/python/runner.py +++ b/test/python/runner.py @@ -2,6 +2,5 @@ import pytest - if __name__ == "__main__": exit(pytest.main(sys.argv[1:])) diff --git a/test/python/unit/test_basics.py b/test/python/unit/test_basics.py index 4e72d8be5c..fab7b5297c 100644 --- a/test/python/unit/test_basics.py +++ b/test/python/unit/test_basics.py @@ -53,9 +53,7 @@ def test_send_data_str(http_server_url: str): assert json.get("headers", {}).get("charset") == "utf8" -@pytest.mark.parametrize( - "data", [{"hello": "world encoding"}, [("hello", "world encoding")]] -) +@pytest.mark.parametrize("data", [{"hello": "world encoding"}, [("hello", "world encoding")]]) def test_send_data_form_urlencoded(http_server_url: str, data): response = envoy_requests.post( http_server_url, @@ -66,10 +64,7 @@ def test_send_data_form_urlencoded(http_server_url: str, data): assert json.get("body") == "hello=world+encoding" assert json.get("method") == "POST" assert json.get("path") == "/" - assert ( - json.get("headers", {}).get("content-type") - == "application/x-www-form-urlencoded" - ) + assert (json.get("headers", {}).get("content-type") == "application/x-www-form-urlencoded") assert json.get("headers", {}).get("charset") == "utf8" @@ -77,6 +72,5 @@ def test_envoy_error(): response = envoy_requests.get("http://127.0.0.1:0/fake-url") assert response.envoy_error is not None assert response.envoy_error.error_code == envoy_requests.ErrorCode.ConnectionFailure - assert re.match(( - "^upstream_reset_before_response_started{connection_failure" - ), response.envoy_error.message) + assert re.match(("^upstream_reset_before_response_started{connection_failure"), + response.envoy_error.message) diff --git a/test/python/unit/test_echo_server.py b/test/python/unit/test_echo_server.py index 49f7eaf39a..27a64c6687 100644 --- a/test/python/unit/test_echo_server.py +++ b/test/python/unit/test_echo_server.py @@ -1,6 +1,5 @@ import requests - # since we already have requests installed for the benchmark # we reuse it to make sure that the echo server works as expected # requests provides a basis of correctness against which we can diff --git a/test/python/unit/test_methods.py b/test/python/unit/test_methods.py index 5b5168a9ac..d7c5e87c2d 100644 --- a/test/python/unit/test_methods.py +++ b/test/python/unit/test_methods.py @@ -5,7 +5,6 @@ from library.python.envoy_requests import threading from library.python.envoy_requests.response import Response - METHODS = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "TRACE"] diff --git a/test/python/unit/test_pre_build_engine.py b/test/python/unit/test_pre_build_engine.py index f4d81cbce7..16e1c4a1df 100644 --- a/test/python/unit/test_pre_build_engine.py +++ b/test/python/unit/test_pre_build_engine.py @@ -20,7 +20,6 @@ def spy_on_build(impl): yield spied_build - @pytest.mark.standalone @pytest.mark.asyncio async def test_pre_build_engine_asyncio(): diff --git a/test/swift/integration/IdleTimeoutTest.swift b/test/swift/integration/IdleTimeoutTest.swift index fd31bde902..d7d1d63841 100644 --- a/test/swift/integration/IdleTimeoutTest.swift +++ b/test/swift/integration/IdleTimeoutTest.swift @@ -81,13 +81,6 @@ static_resources: - endpoint: address: socket_address: { address: 127.0.0.1, port_value: \(remotePort) } -layered_runtime: - layers: - - name: static_layer_0 - static_layer: - envoy: - reloadable_features: - override_request_timeout_by_gateway_timeout: false """ class IdleTimeoutValidationFilter: AsyncResponseFilter, ResponseFilter { @@ -133,7 +126,7 @@ layered_runtime: } func onError(_ error: EnvoyError, streamIntel: FinalStreamIntel) { - XCTAssertEqual(error.errorCode, 4) + XCTAssertEqual(error.errorCode, 0) timeoutExpectation.fulfill() } @@ -166,7 +159,7 @@ layered_runtime: client .newStreamPrototype() .setOnError { error, _ in - XCTAssertEqual(error.errorCode, 4) + XCTAssertEqual(error.errorCode, 0) callbackExpectation.fulfill() } .setOnCancel { _ in diff --git a/third_party/python/requirements.in b/third_party/python/requirements.in new file mode 100644 index 0000000000..5b08c109f8 --- /dev/null +++ b/third_party/python/requirements.in @@ -0,0 +1,6 @@ +gevent +mypy +pytest +pytest-asyncio +pytest-benchmark +requests diff --git a/third_party/python/requirements.txt b/third_party/python/requirements.txt index 5b08c109f8..953ff4231f 100644 --- a/third_party/python/requirements.txt +++ b/third_party/python/requirements.txt @@ -1,6 +1,269 @@ -gevent -mypy -pytest -pytest-asyncio -pytest-benchmark -requests +# +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: +# +# pip-compile --allow-unsafe --generate-hashes requirements.in +# +attrs==22.1.0 \ + --hash=sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6 \ + --hash=sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c + # via pytest +certifi==2022.9.24 \ + --hash=sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14 \ + --hash=sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382 + # via requests +charset-normalizer==2.1.1 \ + --hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 \ + --hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f + # via requests +exceptiongroup==1.0.0 \ + --hash=sha256:2ac84b496be68464a2da60da518af3785fff8b7ec0d090a581604bc870bdee41 \ + --hash=sha256:affbabf13fb6e98988c38d9c5650e701569fe3c1de3233cfb61c5f33774690ad + # via pytest +gevent==22.10.1 \ + --hash=sha256:03c10ca0beeab0c6be516030471ea630447ddd1f649d3335e5b162097cd4130a \ + --hash=sha256:04a920a812b6c0c36d4613a15c254ca1ce415ee75ade0df3b8941ab61ae7ce3f \ + --hash=sha256:0569e133bb620de1001ac807ad9a8abaadedd25349c6d695f80c9048a3f59d42 \ + --hash=sha256:06ea39c70ce166c4a1d4386c7fae96cb8d84ad799527b3378406051104d15443 \ + --hash=sha256:0cafb8f5399224990a5329bca3606bf399ee3604ae711b2d9238129b44551ad5 \ + --hash=sha256:1ac816f5e8e318c5fa27091ee43fcf4caaa6ae73a487e875a1a296a04c3da5af \ + --hash=sha256:1e1c609f9e4171588006bea7ff41bb830ff27c27d071bbd311f91860fb5ef4cc \ + --hash=sha256:1ec5f77f629d997668983be53bad2a90d1b858a00e43b9e75e1c9a118c3a840b \ + --hash=sha256:21dbeb6d3b47093f40ca97aab493b2fb64b6f22112f88f56d79cf6f52a8c1c16 \ + --hash=sha256:2dcfd8ef9dcca78c51dd266d0f4b48d9b7ea2592ae881bf66d8dbe59bb16631a \ + --hash=sha256:33c4cd095f99768ecc4b3bb75a12f52ea9df5c40a58671c667f86ea087a075e1 \ + --hash=sha256:36e47ca663081a71fca137b7c852e99e7ee3761082070c13aa2ae3b5b6234af6 \ + --hash=sha256:3c1cfd9f9fb6a2a5a9a04132d315db7fb819db019dea260695fe6e4012416f96 \ + --hash=sha256:3e73c9f71aa2a6795ecbec9b57282b002375e863e283558feb87b62840c8c1ac \ + --hash=sha256:3f7d11136b3ae6312effbc2ac0ed902ae718d86e7acb9a51cf927262cfb2931e \ + --hash=sha256:4b0d29fc18ee338a85396facfc508e5f26e2e0e90f4c2889f8a9e74d341ad467 \ + --hash=sha256:4be5859af086de1ed85702c0a84479387087ddf49e38332c41861b0a10e96d8f \ + --hash=sha256:4c06c0f3f4f1b147f51a934fbf541880cee769492b98c4ebd3e930b5ff862646 \ + --hash=sha256:5bc3758f0dc95007c1780d28a9fd2150416a79c50f308f62a674d78a845ea1b9 \ + --hash=sha256:5d64b208bec99adc7e0b6e08a3e2c296065c665ca725ca8da434c4ffc5aa302e \ + --hash=sha256:702a51b8f21bad1976b0893f90ade466e8c27039b846b611ad2beb8c6e6ac701 \ + --hash=sha256:7e8c4ccc544f6e6c26ab10d0d6a7be86bd522222ce40f00bfafa01289f04bffc \ + --hash=sha256:a12443b7326e40d00fb445d37bae154fd1f4693055330c6b4e68670ca3b6e6bf \ + --hash=sha256:a838437b7b629328ad457cd36df454500afe7f3df4b971a6ff85851dfcf8c844 \ + --hash=sha256:acb21bee2e66da45b8916073c8ae54c44629beb94d49120c188d27aff4ebf8dd \ + --hash=sha256:af7baec79a5f8ad1cc132d3b14edd12661c628d8094e501b089b1fe2d3df7f6e \ + --hash=sha256:be43278781d39b4081f7f4d3e8ebb1dac188c9fe98f25da817325cb12c01887a \ + --hash=sha256:cf6dd33052919de8fb56e0bea0e6a7c7d6545281fe280ea78e311621c7adb50e \ + --hash=sha256:d18fcc324f39a3b21795022eb47c7752d6e4f4ed89d8cca41f1cc604553265b3 \ + --hash=sha256:d2ea4ce36c09355379bc038be2bd50118f97d2eb6381b7096de4d05aa4c3e241 \ + --hash=sha256:d701208d4d65dbdf9feb02561a75ecc5bd28300e47b59f74033a07b593887806 \ + --hash=sha256:d8df3f628c8a9fb339b87a849dc2076e56d124e2169261fa58b4a01db3a335b6 \ + --hash=sha256:db592cfe5106730667ac36f43554e7a869d757e411f8a08116c3739cee507145 \ + --hash=sha256:df3042349c9a4460eeaec8d0e56d737cb183eed055e75a6af9dbda94aaddaf4d \ + --hash=sha256:eb0d9d6f869ba7c49d7f9b7d244dd20daec5cc87cd3e2e90209d6ed8172e0cad \ + --hash=sha256:eefcb21fda3055f2e7eaad2e8098885a7bbddd83b174b012e2142db6b2b4c09d \ + --hash=sha256:f16c6937d47593f051fc3ac7996c819919082a1e7e0dec927cdae8771d26ed45 \ + --hash=sha256:fe2c0ff095171c49f78f1d4e6dc89fa58253783c7b6dccab9f1d76e2ee391f10 + # via -r requirements.in +greenlet==1.1.3.post0 \ + --hash=sha256:0120a879aa2b1ac5118bce959ea2492ba18783f65ea15821680a256dfad04754 \ + --hash=sha256:025b8de2273d2809f027d347aa2541651d2e15d593bbce0d5f502ca438c54136 \ + --hash=sha256:05ae7383f968bba4211b1fbfc90158f8e3da86804878442b4fb6c16ccbcaa519 \ + --hash=sha256:0914f02fcaa8f84f13b2df4a81645d9e82de21ed95633765dd5cc4d3af9d7403 \ + --hash=sha256:0971d37ae0eaf42344e8610d340aa0ad3d06cd2eee381891a10fe771879791f9 \ + --hash=sha256:0a954002064ee919b444b19c1185e8cce307a1f20600f47d6f4b6d336972c809 \ + --hash=sha256:0aa1845944e62f358d63fcc911ad3b415f585612946b8edc824825929b40e59e \ + --hash=sha256:104f29dd822be678ef6b16bf0035dcd43206a8a48668a6cae4d2fe9c7a7abdeb \ + --hash=sha256:11fc7692d95cc7a6a8447bb160d98671ab291e0a8ea90572d582d57361360f05 \ + --hash=sha256:17a69967561269b691747e7f436d75a4def47e5efcbc3c573180fc828e176d80 \ + --hash=sha256:2794eef1b04b5ba8948c72cc606aab62ac4b0c538b14806d9c0d88afd0576d6b \ + --hash=sha256:2c6e942ca9835c0b97814d14f78da453241837419e0d26f7403058e8db3e38f8 \ + --hash=sha256:2ccdc818cc106cc238ff7eba0d71b9c77be868fdca31d6c3b1347a54c9b187b2 \ + --hash=sha256:325f272eb997916b4a3fc1fea7313a8adb760934c2140ce13a2117e1b0a8095d \ + --hash=sha256:39464518a2abe9c505a727af7c0b4efff2cf242aa168be5f0daa47649f4d7ca8 \ + --hash=sha256:3a24f3213579dc8459e485e333330a921f579543a5214dbc935bc0763474ece3 \ + --hash=sha256:3aeac044c324c1a4027dca0cde550bd83a0c0fbff7ef2c98df9e718a5086c194 \ + --hash=sha256:3c22998bfef3fcc1b15694818fc9b1b87c6cc8398198b96b6d355a7bcb8c934e \ + --hash=sha256:467b73ce5dcd89e381292fb4314aede9b12906c18fab903f995b86034d96d5c8 \ + --hash=sha256:4a8b58232f5b72973350c2b917ea3df0bebd07c3c82a0a0e34775fc2c1f857e9 \ + --hash=sha256:4f74aa0092602da2069df0bc6553919a15169d77bcdab52a21f8c5242898f519 \ + --hash=sha256:5662492df0588a51d5690f6578f3bbbd803e7f8d99a99f3bf6128a401be9c269 \ + --hash=sha256:5c2d21c2b768d8c86ad935e404cc78c30d53dea009609c3ef3a9d49970c864b5 \ + --hash=sha256:5edf75e7fcfa9725064ae0d8407c849456553a181ebefedb7606bac19aa1478b \ + --hash=sha256:60839ab4ea7de6139a3be35b77e22e0398c270020050458b3d25db4c7c394df5 \ + --hash=sha256:62723e7eb85fa52e536e516ee2ac91433c7bb60d51099293671815ff49ed1c21 \ + --hash=sha256:64e10f303ea354500c927da5b59c3802196a07468332d292aef9ddaca08d03dd \ + --hash=sha256:66aa4e9a726b70bcbfcc446b7ba89c8cec40f405e51422c39f42dfa206a96a05 \ + --hash=sha256:695d0d8b5ae42c800f1763c9fce9d7b94ae3b878919379150ee5ba458a460d57 \ + --hash=sha256:70048d7b2c07c5eadf8393e6398595591df5f59a2f26abc2f81abca09610492f \ + --hash=sha256:7afa706510ab079fd6d039cc6e369d4535a48e202d042c32e2097f030a16450f \ + --hash=sha256:7cf37343e43404699d58808e51f347f57efd3010cc7cee134cdb9141bd1ad9ea \ + --hash=sha256:8149a6865b14c33be7ae760bcdb73548bb01e8e47ae15e013bf7ef9290ca309a \ + --hash=sha256:814f26b864ed2230d3a7efe0336f5766ad012f94aad6ba43a7c54ca88dd77cba \ + --hash=sha256:82a38d7d2077128a017094aff334e67e26194f46bd709f9dcdacbf3835d47ef5 \ + --hash=sha256:83a7a6560df073ec9de2b7cb685b199dfd12519bc0020c62db9d1bb522f989fa \ + --hash=sha256:8415239c68b2ec9de10a5adf1130ee9cb0ebd3e19573c55ba160ff0ca809e012 \ + --hash=sha256:88720794390002b0c8fa29e9602b395093a9a766b229a847e8d88349e418b28a \ + --hash=sha256:890f633dc8cb307761ec566bc0b4e350a93ddd77dc172839be122be12bae3e10 \ + --hash=sha256:8926a78192b8b73c936f3e87929931455a6a6c6c385448a07b9f7d1072c19ff3 \ + --hash=sha256:8c0581077cf2734569f3e500fab09c0ff6a2ab99b1afcacbad09b3c2843ae743 \ + --hash=sha256:8fda1139d87ce5f7bd80e80e54f9f2c6fe2f47983f1a6f128c47bf310197deb6 \ + --hash=sha256:91a84faf718e6f8b888ca63d0b2d6d185c8e2a198d2a7322d75c303e7097c8b7 \ + --hash=sha256:924df1e7e5db27d19b1359dc7d052a917529c95ba5b8b62f4af611176da7c8ad \ + --hash=sha256:949c9061b8c6d3e6e439466a9be1e787208dec6246f4ec5fffe9677b4c19fcc3 \ + --hash=sha256:9649891ab4153f217f319914455ccf0b86986b55fc0573ce803eb998ad7d6854 \ + --hash=sha256:96656c5f7c95fc02c36d4f6ef32f4e94bb0b6b36e6a002c21c39785a4eec5f5d \ + --hash=sha256:a812df7282a8fc717eafd487fccc5ba40ea83bb5b13eb3c90c446d88dbdfd2be \ + --hash=sha256:a8d24eb5cb67996fb84633fdc96dbc04f2d8b12bfcb20ab3222d6be271616b67 \ + --hash=sha256:bef49c07fcb411c942da6ee7d7ea37430f830c482bf6e4b72d92fd506dd3a427 \ + --hash=sha256:bffba15cff4802ff493d6edcf20d7f94ab1c2aee7cfc1e1c7627c05f1102eee8 \ + --hash=sha256:c0643250dd0756f4960633f5359884f609a234d4066686754e834073d84e9b51 \ + --hash=sha256:c6f90234e4438062d6d09f7d667f79edcc7c5e354ba3a145ff98176f974b8132 \ + --hash=sha256:c8c9301e3274276d3d20ab6335aa7c5d9e5da2009cccb01127bddb5c951f8870 \ + --hash=sha256:c8ece5d1a99a2adcb38f69af2f07d96fb615415d32820108cd340361f590d128 \ + --hash=sha256:cb863057bed786f6622982fb8b2c122c68e6e9eddccaa9fa98fd937e45ee6c4f \ + --hash=sha256:ccbe7129a282ec5797df0451ca1802f11578be018a32979131065565da89b392 \ + --hash=sha256:d25cdedd72aa2271b984af54294e9527306966ec18963fd032cc851a725ddc1b \ + --hash=sha256:d75afcbb214d429dacdf75e03a1d6d6c5bd1fa9c35e360df8ea5b6270fb2211c \ + --hash=sha256:d7815e1519a8361c5ea2a7a5864945906f8e386fa1bc26797b4d443ab11a4589 \ + --hash=sha256:eb6ac495dccb1520667cfea50d89e26f9ffb49fa28496dea2b95720d8b45eb54 \ + --hash=sha256:ec615d2912b9ad807afd3be80bf32711c0ff9c2b00aa004a45fd5d5dde7853d9 \ + --hash=sha256:f5e09dc5c6e1796969fd4b775ea1417d70e49a5df29aaa8e5d10675d9e11872c \ + --hash=sha256:f6661b58412879a2aa099abb26d3c93e91dedaba55a6394d1fb1512a77e85de9 \ + --hash=sha256:f7d20c3267385236b4ce54575cc8e9f43e7673fc761b069c820097092e318e3b \ + --hash=sha256:fe7c51f8a2ab616cb34bc33d810c887e89117771028e1e3d3b77ca25ddeace04 + # via gevent +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 + # via requests +iniconfig==1.1.1 \ + --hash=sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3 \ + --hash=sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32 + # via pytest +mypy==0.982 \ + --hash=sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d \ + --hash=sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24 \ + --hash=sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046 \ + --hash=sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e \ + --hash=sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3 \ + --hash=sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5 \ + --hash=sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20 \ + --hash=sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda \ + --hash=sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1 \ + --hash=sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146 \ + --hash=sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206 \ + --hash=sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746 \ + --hash=sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6 \ + --hash=sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e \ + --hash=sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc \ + --hash=sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a \ + --hash=sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8 \ + --hash=sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763 \ + --hash=sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2 \ + --hash=sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947 \ + --hash=sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40 \ + --hash=sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b \ + --hash=sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795 \ + --hash=sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c + # via -r requirements.in +mypy-extensions==0.4.3 \ + --hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \ + --hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8 + # via mypy +packaging==21.3 \ + --hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \ + --hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522 + # via pytest +pluggy==1.0.0 \ + --hash=sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159 \ + --hash=sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3 + # via pytest +py-cpuinfo==9.0.0 \ + --hash=sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690 \ + --hash=sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5 + # via pytest-benchmark +pyparsing==3.0.9 \ + --hash=sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb \ + --hash=sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc + # via packaging +pytest==7.2.0 \ + --hash=sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71 \ + --hash=sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59 + # via + # -r requirements.in + # pytest-asyncio + # pytest-benchmark +pytest-asyncio==0.20.1 \ + --hash=sha256:2c85a835df33fda40fe3973b451e0c194ca11bc2c007eabff90bb3d156fc172b \ + --hash=sha256:626699de2a747611f3eeb64168b3575f70439b06c3d0206e6ceaeeb956e65519 + # via -r requirements.in +pytest-benchmark==4.0.0 \ + --hash=sha256:fb0785b83efe599a6a956361c0691ae1dbb5318018561af10f3e915caa0048d1 \ + --hash=sha256:fdb7db64e31c8b277dff9850d2a2556d8b60bcb0ea6524e36e28ffd7c87f71d6 + # via -r requirements.in +requests==2.28.1 \ + --hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \ + --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349 + # via -r requirements.in +tomli==2.0.1 \ + --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ + --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f + # via + # mypy + # pytest +typing-extensions==4.4.0 \ + --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \ + --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e + # via mypy +urllib3==1.26.12 \ + --hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \ + --hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997 + # via requests +zope-event==4.5.0 \ + --hash=sha256:2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42 \ + --hash=sha256:5e76517f5b9b119acf37ca8819781db6c16ea433f7e2062c4afc2b6fbedb1330 + # via gevent +zope-interface==5.5.0 \ + --hash=sha256:006f8dd81fae28027fc28ada214855166712bf4f0bfbc5a8788f9b70982b9437 \ + --hash=sha256:03f5ae315db0d0de668125d983e2a819a554f3fdb2d53b7e934e3eb3c3c7375d \ + --hash=sha256:0eb2b3e84f48dd9cfc8621c80fba905d7e228615c67f76c7df7c716065669bb6 \ + --hash=sha256:1e3495bb0cdcea212154e558082c256f11b18031f05193ae2fb85d048848db14 \ + --hash=sha256:26c1456520fdcafecc5765bec4783eeafd2e893eabc636908f50ee31fe5c738c \ + --hash=sha256:2cb3003941f5f4fa577479ac6d5db2b940acb600096dd9ea9bf07007f5cab46f \ + --hash=sha256:37ec9ade9902f412cc7e7a32d71f79dec3035bad9bd0170226252eed88763c48 \ + --hash=sha256:3eedf3d04179774d750e8bb4463e6da350956a50ed44d7b86098e452d7ec385e \ + --hash=sha256:3f68404edb1a4fb6aa8a94675521ca26c83ebbdbb90e894f749ae0dc4ca98418 \ + --hash=sha256:423c074e404f13e6fa07f4454f47fdbb38d358be22945bc812b94289d9142374 \ + --hash=sha256:43490ad65d4c64e45a30e51a2beb7a6b63e1ff395302ad22392224eb618476d6 \ + --hash=sha256:47ff078734a1030c48103422a99e71a7662d20258c00306546441adf689416f7 \ + --hash=sha256:58a66c2020a347973168a4a9d64317bac52f9fdfd3e6b80b252be30da881a64e \ + --hash=sha256:58a975f89e4584d0223ab813c5ba4787064c68feef4b30d600f5e01de90ae9ce \ + --hash=sha256:5c6023ae7defd052cf76986ce77922177b0c2f3913bea31b5b28fbdf6cb7099e \ + --hash=sha256:6566b3d2657e7609cd8751bcb1eab1202b1692a7af223035a5887d64bb3a2f3b \ + --hash=sha256:687cab7f9ae18d2c146f315d0ca81e5ffe89a139b88277afa70d52f632515854 \ + --hash=sha256:700ebf9662cf8df70e2f0cb4988e078c53f65ee3eefd5c9d80cf988c4175c8e3 \ + --hash=sha256:740f3c1b44380658777669bcc42f650f5348e53797f2cee0d93dc9b0f9d7cc69 \ + --hash=sha256:7bdcec93f152e0e1942102537eed7b166d6661ae57835b20a52a2a3d6a3e1bf3 \ + --hash=sha256:7d9ec1e6694af39b687045712a8ad14ddcb568670d5eb1b66b48b98b9312afba \ + --hash=sha256:85dd6dd9aaae7a176948d8bb62e20e2968588fd787c29c5d0d964ab475168d3d \ + --hash=sha256:8b9f153208d74ccfa25449a0c6cb756ab792ce0dc99d9d771d935f039b38740c \ + --hash=sha256:8c791f4c203ccdbcda588ea4c8a6e4353e10435ea48ddd3d8734a26fe9714cba \ + --hash=sha256:970661ece2029915b8f7f70892e88404340fbdefd64728380cad41c8dce14ff4 \ + --hash=sha256:9cdc4e898d3b1547d018829fd4a9f403e52e51bba24be0fbfa37f3174e1ef797 \ + --hash=sha256:9dc4493aa3d87591e3d2bf1453e25b98038c839ca8e499df3d7106631b66fe83 \ + --hash=sha256:a69c28d85bb7cf557751a5214cb3f657b2b035c8c96d71080c1253b75b79b69b \ + --hash=sha256:aeac590cce44e68ee8ad0b8ecf4d7bf15801f102d564ca1b0eb1f12f584ee656 \ + --hash=sha256:be11fce0e6af6c0e8d93c10ef17b25aa7c4acb7ec644bff2596c0d639c49e20f \ + --hash=sha256:cbbf83914b9a883ab324f728de869f4e406e0cbcd92df7e0a88decf6f9ab7d5a \ + --hash=sha256:cfa614d049667bed1c737435c609c0956c5dc0dbafdc1145ee7935e4658582cb \ + --hash=sha256:d18fb0f6c8169d26044128a2e7d3c39377a8a151c564e87b875d379dbafd3930 \ + --hash=sha256:d80f6236b57a95eb19d5e47eb68d0296119e1eff6deaa2971ab8abe3af918420 \ + --hash=sha256:da7912ae76e1df6a1fb841b619110b1be4c86dfb36699d7fd2f177105cdea885 \ + --hash=sha256:df6593e150d13cfcce69b0aec5df7bc248cb91e4258a7374c129bb6d56b4e5ca \ + --hash=sha256:f70726b60009433111fe9928f5d89cbb18962411d33c45fb19eb81b9bbd26fcd + # via gevent + +# The following packages are considered to be unsafe in a requirements file: +setuptools==65.5.0 \ + --hash=sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17 \ + --hash=sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356 + # via + # gevent + # zope-event + # zope-interface diff --git a/tools/bump_lyft_support_rotation.sh b/tools/bump_lyft_support_rotation.sh index a732dcfbc6..2b8775f1e2 100755 --- a/tools/bump_lyft_support_rotation.sh +++ b/tools/bump_lyft_support_rotation.sh @@ -48,7 +48,7 @@ previous=${first_line#"current: "} next="$(next_maintainer "$previous" "$maintainers_file")" set_maintainer "$next" "$maintainers_file" -echo "::set-output name=PREVIOUS_MAINTAINER::$previous" -echo "::set-output name=NEXT_MAINTAINER::$next" +echo "PREVIOUS_MAINTAINER=$previous" >> "$GITHUB_OUTPUT" +echo "NEXT_MAINTAINER=$next" >> "$GITHUB_OUTPUT" echo "Lyft support maintainer changing from $previous to $next" diff --git a/tools/check_format.sh b/tools/check_format.sh index ed4f1bad26..b22f81754c 100755 --- a/tools/check_format.sh +++ b/tools/check_format.sh @@ -25,6 +25,6 @@ TARGET_PATH="$2" ENVOY_BAZEL_PREFIX=@envoy envoy/tools/code_format/check_format.py \ --config_path envoy/tools/code_format/config.yaml \ --add-excluded-prefixes ./envoy/ ./envoy_build_config/extensions_build_config.bzl ./WORKSPACE ./Envoy.xcodeproj/ ./dist/ ./library/common/config_template.cc ./bazel/envoy_mobile_swift_bazel_support.bzl ./bazel/envoy_mobile_repositories.bzl ./examples/swift/swiftpm/Packages/Envoy.xcframework \ - --skip_envoy_build_rule_check "$ENVOY_FORMAT_ACTION" $TARGET_PATH \ + --skip_envoy_build_rule_check "$ENVOY_FORMAT_ACTION" "$TARGET_PATH" \ --namespace_check_excluded_paths ./envoy ./examples/ ./library/java/ ./library/kotlin ./library/objective-c ./test/java ./test/java ./test/objective-c ./test/swift ./experimental/swift \ --build_fixer_check_excluded_paths ./envoy ./BUILD ./dist ./examples ./library/java ./library/kotlin ./library/objective-c ./library/swift ./library/common/extensions ./test/java ./test/kotlin ./test/objective-c ./test/swift ./experimental/swift