diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml index b7a7948d2cf..1cd1dd8b939 100644 --- a/.github/actions/build-test-image/action.yml +++ b/.github/actions/build-test-image/action.yml @@ -15,7 +15,7 @@ inputs: required: false suites: description: The test suites to build into the image - default: chaos migration performance reorg smoke soak benchmark load/automationv2_1 + default: chaos migration reorg smoke soak benchmark load/automationv2_1 required: false QA_AWS_ROLE_TO_ASSUME: description: The AWS role to assume as the CD user, if any. Used in configuring the docker/login-action diff --git a/.github/actions/setup-create-base64-config-live-testnets/action.yml b/.github/actions/setup-create-base64-config-live-testnets/action.yml new file mode 100644 index 00000000000..5ba8150989a --- /dev/null +++ b/.github/actions/setup-create-base64-config-live-testnets/action.yml @@ -0,0 +1,130 @@ +name: Create Base64 Config +description: A composite action that creates a base64-encoded config to be used by integration tests + +inputs: + runId: + description: The run id + testLogCollect: + description: Whether to always collect logs, even for passing tests + default: "false" + chainlinkImage: + description: The chainlink image to use + default: "public.ecr.aws/chainlink/chainlink" + chainlinkVersion: + description: The git commit sha to use for the image tag + pyroscopeServer: + description: URL of Pyroscope server + pyroscopeEnvironment: + description: Name of Pyroscope environment + pyroscopeKey: + description: Pyroscope server key + lokiEndpoint: + description: Loki push endpoint + lokiTenantId: + description: Loki tenant id + lokiBasicAuth: + description: Loki basic auth + logstreamLogTargets: + description: Where to send logs (e.g. file, loki) + grafanaUrl: + description: Grafana URL + grafanaDashboardUrl: + description: Grafana dashboard URL + network: + description: Network to run tests on + httpEndpoints: + description: HTTP endpoints to use for network + wsEndpoints: + description: WS endpoints to use for network + fundingKeys: + description: Funding keys to use for network + +runs: + using: composite + steps: + - name: Prepare Base64 TOML override + shell: bash + id: base64-config-override + env: + RUN_ID: ${{ inputs.runId }} + PYROSCOPE_SERVER: ${{ inputs.pyroscopeServer }} + PYROSCOPE_ENVIRONMENT: ${{ inputs.pyroscopeEnvironment }} + PYROSCOPE_KEY: ${{ inputs.pyroscopeKey }} + CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} + CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} + LOKI_ENDPOINT: ${{ inputs.lokiEndpoint }} + LOKI_TENANT_ID: ${{ inputs.lokiTenantId }} + LOKI_BASIC_AUTH: ${{ inputs.lokiBasicAuth }} + LOGSTREAM_LOG_TARGETS: ${{ inputs.logstreamLogTargets }} + GRAFANA_URL: ${{ inputs.grafanaUrl }} + GRAFANA_DASHBOARD_URL: ${{ inputs.grafanaDashboardUrl }} + NETWORK: ${{ inputs.network }} + HTTP_ENDPOINTS: ${{ inputs.httpEndpoints }} + WS_ENDPOINTS: ${{ inputs.wsEndpoints }} + FUNDING_KEYS: ${{ inputs.fundingKeys }} + run: | + convert_to_toml_array() { + local IFS=',' + local input_array=($1) + local toml_array_format="[" + + for element in "${input_array[@]}"; do + toml_array_format+="\"$element\"," + done + + toml_array_format="${toml_array_format%,}]" + echo "$toml_array_format" + } + + if [ -n "$PYROSCOPE_SERVER" ]; then + pyroscope_enabled=true + else + pyroscope_enabled=false + fi + + cat << EOF > config.toml + [Common] + chainlink_node_funding=0.5 + + [ChainlinkImage] + image="$CHAINLINK_IMAGE" + version="$CHAINLINK_VERSION" + + [Pyroscope] + enabled=$pyroscope_enabled + server_url="$PYROSCOPE_SERVER" + environment="$PYROSCOPE_ENVIRONMENT" + key="$PYROSCOPE_KEY" + + [Logging] + run_id="$RUN_ID" + + [Logging.LogStream] + log_targets=$(convert_to_toml_array "$LOGSTREAM_LOG_TARGETS") + + [Logging.Loki] + tenant_id="$LOKI_TENANT_ID" + endpoint="$LOKI_URL" + basic_auth="$LOKI_BASIC_AUTH" + + [Logging.Grafana] + base_url="$GRAFANA_URL" + dasboard_url="$GRAFANA_DASHBOARD_URL" + + [Network] + selected_networks=["$NETWORK"] + + [Network.RpcHttpUrls] + "$NETWORK" = $(convert_to_toml_array "$HTTP_ENDPOINTS") + + [Network.RpcWsUrls] + "$NETWORK" = $(convert_to_toml_array "$WS_ENDPOINTS") + + [Network.WalletKeys] + "$NETWORK" = $(convert_to_toml_array "$FUNDING_KEYS") + EOF + + BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + touch .root_dir diff --git a/.github/actions/setup-create-base64-config/action.yml b/.github/actions/setup-create-base64-config/action.yml new file mode 100644 index 00000000000..eafd670226f --- /dev/null +++ b/.github/actions/setup-create-base64-config/action.yml @@ -0,0 +1,122 @@ +name: Create Base64 Config +description: A composite action that creates a base64-encoded config to be used by integration tests + +inputs: + runId: + description: The run id + testLogCollect: + description: Whether to always collect logs, even for passing tests + default: "false" + selectedNetworks: + description: The networks to run tests against + chainlinkImage: + description: The chainlink image to use + default: "public.ecr.aws/chainlink/chainlink" + chainlinkVersion: + description: The git commit sha to use for the image tag + pyroscopeServer: + description: URL of Pyroscope server + pyroscopeEnvironment: + description: Name of Pyroscope environment + pyroscopeKey: + description: Pyroscope server key + lokiEndpoint: + description: Loki push endpoint + lokiTenantId: + description: Loki tenant id + lokiBasicAuth: + description: Loki basic auth + logstreamLogTargets: + description: Where to send logs (e.g. file, loki) + grafanaUrl: + description: Grafana URL + grafanaDashboardUrl: + description: Grafana dashboard URL + +runs: + using: composite + steps: + - name: Prepare Base64 TOML override + shell: bash + id: base64-config-override + env: + RUN_ID: ${{ inputs.runId }} + TEST_LOG_COLLECT: ${{ inputs.testLogCollect }} + SELECTED_NETWORKS: ${{ inputs.selectedNetworks }} + PYROSCOPE_SERVER: ${{ inputs.pyroscopeServer }} + PYROSCOPE_ENVIRONMENT: ${{ inputs.pyroscopeEnvironment }} + PYROSCOPE_KEY: ${{ inputs.pyroscopeKey }} + CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} + CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} + LOKI_ENDPOINT: ${{ inputs.lokiEndpoint }} + LOKI_TENANT_ID: ${{ inputs.lokiTenantId }} + LOKI_BASIC_AUTH: ${{ inputs.lokiBasicAuth }} + LOGSTREAM_LOG_TARGETS: ${{ inputs.logstreamLogTargets }} + GRAFANA_URL: ${{ inputs.grafanaUrl }} + GRAFANA_DASHBOARD_URL: ${{ inputs.grafanaDashboardUrl }} + run: | + echo ::add-mask::$CHAINLINK_IMAGE + function convert_to_toml_array() { + local IFS=',' + local input_array=($1) + local toml_array_format="[" + + for element in "${input_array[@]}"; do + toml_array_format+="\"$element\"," + done + + toml_array_format="${toml_array_format%,}]" + echo "$toml_array_format" + } + + selected_networks=$(convert_to_toml_array "$SELECTED_NETWORKS") + log_targets=$(convert_to_toml_array "$LOGSTREAM_LOG_TARGETS") + + if [ -n "$PYROSCOPE_SERVER" ]; then + pyroscope_enabled=true + else + pyroscope_enabled=false + fi + + if [ -n "$TEST_LOG_COLLECT" ]; then + test_log_collect=true + else + test_log_collect=false + fi + + cat << EOF > config.toml + [Network] + selected_networks=$selected_networks + + [ChainlinkImage] + image="$CHAINLINK_IMAGE" + version="$CHAINLINK_VERSION" + + [Pyroscope] + enabled=$pyroscope_enabled + server_url="$PYROSCOPE_SERVER" + environment="$PYROSCOPE_ENVIRONMENT" + key="$PYROSCOPE_KEY" + + [Logging] + test_log_collect=$test_log_collect + run_id="$RUN_ID" + + [Logging.LogStream] + log_targets=$log_targets + + [Logging.Loki] + tenant_id="$LOKI_TENANT_ID" + endpoint="$LOKI_ENDPOINT" + basic_auth="$LOKI_BASIC_AUTH" + # legacy, you only need this to access the cloud version + # bearer_token="bearer_token" + + [Logging.Grafana] + base_url="$GRAFANA_URL" + dasboard_url="$GRAFANA_DASHBOARD_URL" + EOF + + BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV diff --git a/.github/actions/setup-create-base64-upgrade-config /action.yml b/.github/actions/setup-create-base64-upgrade-config /action.yml new file mode 100644 index 00000000000..f3acde2ea97 --- /dev/null +++ b/.github/actions/setup-create-base64-upgrade-config /action.yml @@ -0,0 +1,61 @@ +name: Create Base64 Upgrade Config +description: A composite action that creates a base64-encoded config to be used by Chainlink version upgrade tests + +inputs: + selectedNetworks: + description: The networks to run tests against + chainlinkImage: + description: The chainlink image to upgrade from + default: "public.ecr.aws/chainlink/chainlink" + chainlinkVersion: + description: The git commit sha to use for the image tag + upgradeImage: + description: The chainlink image to upgrade to + default: "public.ecr.aws/chainlink/chainlink" + upgradeVersion: + description: The git commit sha to use for the image tag + +runs: + using: composite + steps: + - name: Prepare Base64 TOML override + shell: bash + id: base64-config-override + env: + SELECTED_NETWORKS: ${{ inputs.selectedNetworks }} + CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} + CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} + UPGRADE_IMAGE: ${{ inputs.upgradeImage }} + UPGRADE_VERSION: ${{ inputs.upgradeVersion }} + run: | + function convert_to_toml_array() { + local IFS=',' + local input_array=($1) + local toml_array_format="[" + + for element in "${input_array[@]}"; do + toml_array_format+="\"$element\"," + done + + toml_array_format="${toml_array_format%,}]" + echo "$toml_array_format" + } + + selected_networks=$(convert_to_toml_array "$SELECTED_NETWORKS") + + cat << EOF > config.toml + [Network] + selected_networks=$selected_networks + + [ChainlinkImage] + image="$CHAINLINK_IMAGE" + version="$CHAINLINK_VERSION" + + [ChainlinkUpgradeImage] + image="$UPGRADE_IMAGE" + version="$UPGRADE_VERSION" + EOF + + BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV diff --git a/.github/actions/setup-merge-base64-config/action.yml b/.github/actions/setup-merge-base64-config/action.yml new file mode 100644 index 00000000000..e5bf2a7d276 --- /dev/null +++ b/.github/actions/setup-merge-base64-config/action.yml @@ -0,0 +1,54 @@ +name: Merge Base64 Config +description: A composite action that merges user-provided Base64-encoded config with repository's secrets + +inputs: + base64Config: + description: Base64-encoded config to decode + +runs: + using: composite + steps: + - name: Add masks and export base64 config + shell: bash + run: | + BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + + decoded_toml=$(echo $BASE64_CONFIG_OVERRIDE | base64 -d) + CHAINLINK_IMAGE=$(echo "$decoded_toml" | awk -F'=' '/^[[:space:]]*image[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2}' 2>/dev/null) + echo ::add-mask::$CHAINLINK_IMAGE + CHAINLINK_VERSION=$(echo "$decoded_toml" | awk -F'=' '/^[[:space:]]*version[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2}' 2>/dev/null) + NETWORKS=$(echo "$decoded_toml" | awk -F'=' '/^[[:space:]]*selected_networks[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2}' 2>/dev/null) + + if [ -n "$CHAINLINK_IMAGE" ]; then + echo "CHAINLINK_IMAGE=$CHAINLINK_IMAGE" >> $GITHUB_ENV + else + echo "No Chainlink Image found in base64-ed config. Exiting" + exit 1 + fi + if [ -n "$CHAINLINK_VERSION" ]; then + echo "CHAINLINK_VERSION=$CHAINLINK_VERSION" >> $GITHUB_ENV + else + echo "No Chainlink Version found in base64-ed config. Exiting" + exit 1 + fi + if [ -n "$NETWORKS" ]; then + echo "NETWORKS=$NETWORKS" >> $GITHUB_ENV + fi + + # use Loki config from GH secrets and merge it with base64 input + cat << EOF > config.toml + [Logging.Loki] + tenant_id="$LOKI_TENANT_ID" + endpoint="$LOKI_URL" + basic_auth="$LOKI_BASIC_AUTH" + # legacy, you only need this to access the cloud version + # bearer_token="bearer_token" + EOF + + echo "$decoded_toml" >> final_config.toml + cat config.toml >> final_config.toml + BASE64_CONFIG_OVERRIDE=$(cat final_config.toml | base64 -w 0) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV \ No newline at end of file diff --git a/.github/actions/setup-parse-base64-config/action.yml b/.github/actions/setup-parse-base64-config/action.yml new file mode 100644 index 00000000000..a744abae9e0 --- /dev/null +++ b/.github/actions/setup-parse-base64-config/action.yml @@ -0,0 +1,38 @@ +name: Parse Base64 Config +description: A composite action that extracts the chainlink image, version and network from a base64-encoded config + +inputs: + base64Config: + description: Base64-encoded config to decode + +runs: + using: composite + steps: + - name: Add masks and export base64 config + shell: bash + run: | + decoded_toml=$(echo $BASE64_CONFIG_OVERRIDE | base64 -d) + CHAINLINK_IMAGE=$(echo "$decoded_toml" | awk -F'=' '/^[[:space:]]*image[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2}' 2>/dev/null) + echo ::add-mask::$CHAINLINK_IMAGE + CHAINLINK_VERSION=$(echo "$decoded_toml" | awk -F'=' '/^[[:space:]]*version[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2}' 2>/dev/null) + NETWORKS=$(echo "$decoded_toml" | awk -F'=' '/^[[:space:]]*selected_networks[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2}' 2>/dev/null) + ETH2_EL_CLIENT=$(echo "$decoded_toml" | awk -F'=' '/^[[:space:]]*execution_layer[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2}' 2>/dev/null) + + if [ -n "$CHAINLINK_IMAGE" ]; then + echo "CHAINLINK_IMAGE=$CHAINLINK_IMAGE" >> $GITHUB_ENV + else + echo "No Chainlink Image found in base64-ed config. Exiting" + exit 1 + fi + if [ -n "$CHAINLINK_VERSION" ]; then + echo "CHAINLINK_VERSION=$CHAINLINK_VERSION" >> $GITHUB_ENV + else + echo "No Chainlink Version found in base64-ed config. Exiting" + exit 1 + fi + if [ -n "$NETWORKS" ]; then + echo "NETWORKS=$NETWORKS" >> $GITHUB_ENV + fi + if [ -n "$ETH2_EL_CLIENT" ]; then + echo "ETH2_EL_CLIENT=$ETH2_EL_CLIENT" >> $GITHUB_ENV + fi \ No newline at end of file diff --git a/.github/scripts/functions.sh b/.github/scripts/functions.sh new file mode 100644 index 00000000000..53b53392269 --- /dev/null +++ b/.github/scripts/functions.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Function to convert a comma-separated list into a TOML array format. +# Usage: convert_to_toml_array "elem1,elem2,elem3" +# Effect: "a,b,c" -> ["a","b","c"] +function convert_to_toml_array() { + local IFS=',' + local input_array=($1) + local toml_array_format="[" + + for element in "${input_array[@]}"; do + toml_array_format+="\"$element\"," + done + + toml_array_format="${toml_array_format%,}]" + echo "$toml_array_format" +} \ No newline at end of file diff --git a/.github/tracing/README.md b/.github/tracing/README.md index 04f0216e25f..06b2eef6652 100644 --- a/.github/tracing/README.md +++ b/.github/tracing/README.md @@ -9,8 +9,18 @@ One way to generate traces locally today is with the OCR2 basic smoke test. 1. navigate to `.github/tracing/` and then run `docker compose --file local-smoke-docker-compose.yaml up` 2. setup a local docker registry at `127.0.0.1:5000` (https://www.docker.com/blog/how-to-use-your-own-registry-2/) 3. run `make build_push_plugin_docker_image` in `chainlink/integration-tests/Makefile` -4. run `SELECTED_NETWORKS=SIMULATED CHAINLINK_IMAGE="127.0.0.1:5000/chainlink" CHAINLINK_VERSION="develop" go test -run TestOCRv2Basic ./smoke/ocr2_test.go` -5. navigate to `localhost:3000/explore` in a web browser to query for traces +4. preapre your `overrides.toml` file with selected network and CL image name and version and place it anywhere +inside `integration-tests` directory. Sample `overrides.toml` file: +```toml +[ChainlinkImage] +image="127.0.0.1:5000/chainlink" +version="develop" + +[Network] +selected_networks=["simulated"] +``` +5. run `go test -run TestOCRv2Basic ./smoke/ocr2_test.go` +6. navigate to `localhost:3000/explore` in a web browser to query for traces Core and the median plugins are instrumented with open telemetry traces, which are sent to the OTEL collector and forwarded to the Tempo backend. The grafana UI can then read the trace data from the Tempo backend. diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml index b2e5ad1638e..740975ae5ee 100644 --- a/.github/workflows/automation-benchmark-tests.yml +++ b/.github/workflows/automation-benchmark-tests.yml @@ -2,53 +2,20 @@ name: Automation Benchmark Test on: workflow_dispatch: inputs: - chainlinkVersion: - description: Chainlink image version to use + testType: + description: Type of test to run (benchmark, soak) required: true + default: benchmark type: string - default: 2.6.0 - chainlinkImage: - description: Chainlink image repo to use + base64Config: + description: base64-ed config required: true type: string - default: public.ecr.aws/chainlink/chainlink - network: - description: Network to run tests on - required: true - type: choice - options: - - SIMULATED - - SIMULATED_NONDEV - - GOERLI - - ARBITRUM_GOERLI - - OPTIMISM_GOERLI - - MUMBAI - - SEPOLIA - - BASE_GOERLI - - ARBITRUM_SEPOLIA - - LINEA_GOERLI - TestInputs: - description: TestInputs - required: false - type: string - wsURL: - description: WS URL for the network (Skip for Simulated) - required: false - type: string - httpURL: - description: HTTP URL for the network (Skip for Simulated) - required: false - type: string slackMemberID: description: Notifies test results (Not your @) required: true default: U02Q14G80TY type: string - fundingPrivateKey: - description: Private funding key (Skip for Simulated) - required: false - type: string - jobs: automation_benchmark: environment: integration @@ -57,52 +24,40 @@ jobs: pull-requests: write id-token: write contents: read - name: ${{ inputs.network }} Automation Benchmark Test + name: Automation Benchmark Test runs-on: ubuntu20.04-16cores-64GB env: - SELECTED_NETWORKS: ${{ inputs.network }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} SLACK_CHANNEL: C03KJ5S7KEK - TEST_INPUTS: ${{ inputs.TestInputs }} CHAINLINK_ENV_USER: ${{ github.actor }} REF_NAME: ${{ github.head_ref || github.ref_name }} steps: - - name: Setup Push Tag - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - - - name: Add mask + - name: Checkout the repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ env.REF_NAME }} + - name: Get Slack config and mask base64 config run: | - EVM_URLS=$(jq -r '.inputs.wsURL' $GITHUB_EVENT_PATH) - EVM_HTTP_URLS=$(jq -r '.inputs.httpURL' $GITHUB_EVENT_PATH) - EVM_KEYS=$(jq -r '.inputs.fundingPrivateKey' $GITHUB_EVENT_PATH) SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH) - echo ::add-mask::$EVM_URLS - echo ::add-mask::$EVM_HTTP_URLS - echo ::add-mask::$EVM_KEYS echo ::add-mask::$SLACK_USER - echo EVM_URLS=$EVM_URLS >> $GITHUB_ENV - echo EVM_HTTP_URLS=$EVM_HTTP_URLS >> $GITHUB_ENV - echo EVM_KEYS=$EVM_KEYS >> $GITHUB_ENV echo SLACK_USER=$SLACK_USER >> $GITHUB_ENV - while IFS=',' read -ra EVM_URLS_2; do - for i in "${EVM_URLS_2[@]}"; do - echo ::add-mask::$i - done - done <<< "$EVM_URLS" - while IFS=',' read -ra EVM_HTTP_URLS_2; do - for i in "${EVM_HTTP_URLS_2[@]}"; do - echo ::add-mask::$i - done - done <<< "$EVM_HTTP_URLS" - - name: Checkout the repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + - name: Parse base64 config + uses: ./.github/actions/setup-parse-base64-config with: - ref: ${{ env.REF_NAME }} + base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} + - name: Send details to Step Summary + shell: bash + run: | + echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY + echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY + echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY + echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - name: Build Test Image uses: ./.github/actions/build-test-image with: @@ -118,11 +73,13 @@ jobs: TEST_ARGS: -test.timeout 720h ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:${{ github.sha }} INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com + TEST_TYPE: ${{ github.event.inputs.testType }} + TEST_TEST_TYPE: ${{ github.event.inputs.testType }} with: test_command_to_run: cd integration-tests && go test -timeout 30m -v -run ^TestAutomationBenchmark$ ./benchmark -count=1 test_download_vendor_packages_command: make gomod - cl_repo: ${{ inputs.chainlinkImage }} - cl_image_tag: ${{ inputs.chainlinkVersion }} + cl_repo: ${{ env.CHAINLINK_IMAGE }} + cl_image_tag: ${{ env.CHAINLINK_VERSION }} token: ${{ secrets.GITHUB_TOKEN }} should_cleanup: false go_mod_path: ./integration-tests/go.mod @@ -136,6 +93,6 @@ jobs: with: basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} - this-job-name: ${{ inputs.network }} Automation Benchmark Test + this-job-name: Automation Benchmark Test test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' continue-on-error: true diff --git a/.github/workflows/automation-load-tests.yml b/.github/workflows/automation-load-tests.yml index 96dffa01db9..583314f438e 100644 --- a/.github/workflows/automation-load-tests.yml +++ b/.github/workflows/automation-load-tests.yml @@ -2,30 +2,10 @@ name: Automation Load Test on: workflow_dispatch: inputs: - chainlinkVersion: - description: Chainlink image version to use + base64Config: + description: base64-ed config required: true - type: string - default: 2.6.0 - chainlinkImage: - description: Chainlink image repo to use - required: true - type: string - default: public.ecr.aws/chainlink/chainlink - network: - description: Network to run tests on - required: true - type: choice - options: - - SIMULATED - TestInputs: - description: TestInputs - required: false - type: string - ConfigOverride: - description: ConfigOverride - required: false - type: string + type: string slackMemberID: description: Notifies test results (Not your @) required: true @@ -40,34 +20,40 @@ jobs: pull-requests: write id-token: write contents: read - name: ${{ inputs.network }} Automation Load Test + name: Automation Load Test runs-on: ubuntu20.04-16cores-64GB env: - SELECTED_NETWORKS: ${{ inputs.network }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} SLACK_CHANNEL: C03KJ5S7KEK - TEST_INPUTS: ${{ inputs.TestInputs }} - CONFIG_OVERRIDE: ${{ inputs.ConfigOverride }} CHAINLINK_ENV_USER: ${{ github.actor }} REF_NAME: ${{ github.head_ref || github.ref_name }} steps: - - name: Setup Push Tag - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - - - name: Add mask + - name: Checkout the repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ env.REF_NAME }} + - name: Get Slack config and mask base64 config run: | SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH) echo ::add-mask::$SLACK_USER echo SLACK_USER=$SLACK_USER >> $GITHUB_ENV - - name: Checkout the repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + - name: Parse base64 config + uses: ./.github/actions/setup-parse-base64-config with: - ref: ${{ env.REF_NAME }} + base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} + - name: Send details to Step Summary + shell: bash + run: | + echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY + echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY + echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY + echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - name: Build Test Image uses: ./.github/actions/build-test-image with: @@ -90,8 +76,8 @@ jobs: with: test_command_to_run: cd integration-tests && go test -timeout 1h -v -run TestLogTrigger ./load/automationv2_1 -count=1 test_download_vendor_packages_command: make gomod - cl_repo: ${{ inputs.chainlinkImage }} - cl_image_tag: ${{ inputs.chainlinkVersion }} + cl_repo: ${{ env.CHAINLINK_IMAGE }} + cl_image_tag: ${{ env.CHAINLINK_VERSION }} token: ${{ secrets.GITHUB_TOKEN }} should_cleanup: false go_mod_path: ./integration-tests/go.mod @@ -105,6 +91,6 @@ jobs: with: basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} - this-job-name: ${{ inputs.network }} Automation Load Test + this-job-name: Automation Load Test test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' continue-on-error: true diff --git a/.github/workflows/automation-nightly-tests.yml b/.github/workflows/automation-nightly-tests.yml index 9fa3746f3df..9d45ec99e74 100644 --- a/.github/workflows/automation-nightly-tests.yml +++ b/.github/workflows/automation-nightly-tests.yml @@ -71,13 +71,18 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: ref: ${{ github.head_ref || github.ref_name }} + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-upgrade-config + with: + selectedNetworks: ${{ env.SELECTED_NETWORKS }} + chainlinkImage: "public.ecr.aws/chainlink/chainlink" + chainlinkVersion: "latest" + upgradeImage: ${{ env.UPGRADE_IMAGE }} + upgradeVersion: ${{ env.UPGRADE_VERSION }} - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16 env: - SELECTED_NETWORKS: ${{ matrix.tests.network }} TEST_SUITE: ${{ matrix.tests.suite }} - UPGRADE_VERSION: ${{ github.sha }} - UPGRADE_IMAGE: ${{ env.CHAINLINK_IMAGE }} with: test_command_to_run: cd ./integration-tests && go test -timeout 60m -count=1 -json -test.parallel=${{ matrix.tests.nodes }} ${{ matrix.tests.command }} 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml index e023006d58b..ddf26d5607a 100644 --- a/.github/workflows/automation-ondemand-tests.yml +++ b/.github/workflows/automation-ondemand-tests.yml @@ -162,25 +162,70 @@ jobs: echo "upgrade_version=${{ github.sha }}" >>$GITHUB_OUTPUT echo "upgrade_image=${{ env.CHAINLINK_IMAGE }}" >>$GITHUB_OUTPUT else - echo "image=${{ inputs.chainlinkImage }}" >>$GITHUB_OUTPUT + READ_CL_IMAGE=$(jq -r '.inputs.chainlinkImage' $GITHUB_EVENT_PATH) + echo ::add-mask::$READ_CL_IMAGE + echo "image=$READ_CL_IMAGE" >>$GITHUB_OUTPUT echo "version=${{ inputs.chainlinkVersion }}" >>$GITHUB_OUTPUT echo "upgrade_version=${{ inputs.chainlinkVersion }}" >>$GITHUB_OUTPUT - echo "upgrade_image=${{ inputs.chainlinkImage }}" >>$GITHUB_OUTPUT + echo "upgrade_image=$READ_CL_IMAGE" >>$GITHUB_OUTPUT fi if [[ "${{ matrix.tests.name }}" == "upgrade" ]]; then - echo "image=${{ inputs.chainlinkImageUpdate }}" >>$GITHUB_OUTPUT + READ_CL_UPGR_IMAGE=$(jq -r '.inputs.chainlinkImageUpdate' $GITHUB_EVENT_PATH) + echo ::add-mask::$READ_CL_UPGR_IMAGE + echo "image=$READ_CL_UPGR_IMAGE" >>$GITHUB_OUTPUT echo "version=${{ inputs.chainlinkVersionUpdate }}" >>$GITHUB_OUTPUT fi - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16 + - name: Prepare Base64 TOML config env: - PYROSCOPE_SERVER: ${{ matrix.tests.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - PYROSCOPE_ENVIRONMENT: ${{ matrix.tests.pyroscope_env }} - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} SELECTED_NETWORKS: ${{ matrix.tests.network }} - TEST_SUITE: ${{ matrix.tests.suite }} + OLD_IMAGE: ${{ steps.determine-build.outputs.image }} + OLD_VERSION: ${{ steps.determine-build.outputs.version }} UPGRADE_VERSION: ${{ steps.determine-build.outputs.upgrade_version }} UPGRADE_IMAGE: ${{ steps.determine-build.outputs.upgrade_image }} + PYROSCOPE_SERVER: ${{ matrix.tests.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + PYROSCOPE_ENVIRONMENT: ${{ matrix.tests.pyroscope_env }} + PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} + run: | + echo ::add-mask::$UPGRADE_IMAGE + echo ::add-mask::$OLD_IMAGE + + # load reusable functions + source ./.github/scripts/functions.sh + + selected_networks=$(convert_to_toml_array "$SELECTED_NETWORKS") + + if [ -n "$PYROSCOPE_SERVER" ]; then + pyroscope_enabled=true + else + pyroscope_enabled=false + fi + + cat << EOF > config.toml + [Network] + selected_networks=$selected_networks + + [ChainlinkImage] + image="$OLD_IMAGE" + version="$OLD_VERSION" + + [ChainlinkUpgradeImage] + image="$UPGRADE_IMAGE" + version="$UPGRADE_VERSION" + + [Pyroscope] + enabled=$pyroscope_enabled + server_url="$PYROSCOPE_SERVER" + environment="$PYROSCOPE_ENVIRONMENT" + key="$PYROSCOPE_KEY" + EOF + + BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + - name: Run Tests + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16 + env: + TEST_SUITE: ${{ matrix.tests.suite }} with: test_command_to_run: cd ./integration-tests && go test -timeout 60m -count=1 -json -test.parallel=${{ matrix.tests.nodes }} ${{ matrix.tests.command }} 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download diff --git a/.github/workflows/client-compatibility-tests.yml b/.github/workflows/client-compatibility-tests.yml index 865c72258cd..0334d32cae8 100644 --- a/.github/workflows/client-compatibility-tests.yml +++ b/.github/workflows/client-compatibility-tests.yml @@ -67,11 +67,12 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - name: Build Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-tests@912bed7e07a1df4d06ea53a031e9773bb65dc7bd # v2.3.0 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-tests@bce4caa154b1e0e652d042788e14c8870832acd2 # v2.3.0 with: test_download_vendor_packages_command: cd ./integration-tests && go mod download token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod + go_tags: embed cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "true" binary_name: tests @@ -100,43 +101,51 @@ jobs: test: TestOCRBasic file: ocr client: geth + timeout: 30m pyroscope_env: ci-smoke-ocr-geth-simulated # Uncomment, when https://smartcontract-it.atlassian.net/browse/TT-753 is DONE # - name: ocr-nethermind # test: TestOCRBasic # file: ocr # client: nethermind + # timeout: 30m # pyroscope_env: ci-smoke-ocr-nethermind-simulated - name: ocr-besu test: TestOCRBasic file: ocr client: besu + timeout: 30m pyroscope_env: ci-smoke-ocr-besu-simulated - name: ocr-erigon test: TestOCRBasic file: ocr client: erigon + timeout: 30m pyroscope_env: ci-smoke-ocr-erigon-simulated - name: ocr2-geth test: TestOCRv2Basic file: ocr2 client: geth + timeout: 30m pyroscope_env: ci-smoke-ocr2-geth-simulated # Uncomment, when https://smartcontract-it.atlassian.net/browse/TT-753 is DONE # - name: ocr2-nethermind # test: TestOCRv2Basic # file: ocr2 # client: nethermind + # timeout: 30m # pyroscope_env: ci-smoke-nethermind-evm-simulated - name: ocr2-besu test: TestOCRv2Basic file: ocr2 - client: besu + client: besu + timeout: 30m pyroscope_env: ci-smoke-ocr2-besu-simulated - name: ocr2-erigon test: TestOCRv2Basic file: ocr2 - client: erigon + client: erigon + timeout: 60m pyroscope_env: ci-smoke-ocr2-erigon-simulated runs-on: ubuntu-latest name: Client Compatibility Test ${{ matrix.name }} @@ -145,15 +154,79 @@ jobs: uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@912bed7e07a1df4d06ea53a031e9773bb65dc7bd # v2.3.0 + - name: Prepare Base64 TOML config env: + SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} PYROSCOPE_ENVIRONMENT: ci-client-compatability-${{ matrix.client }}-testnet PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} ETH2_EL_CLIENT: ${{matrix.client}} + CHAINLINK_VERSION: ${{ github.sha }} + run: | + convert_to_toml_array() { + local IFS=',' + local input_array=($1) + local toml_array_format="[" + + for element in "${input_array[@]}"; do + toml_array_format+="\"$element\"," + done + + toml_array_format="${toml_array_format%,}]" + echo "$toml_array_format" + } + + selected_networks=$(convert_to_toml_array "$SELECTED_NETWORKS") + + if [ -n "$ETH2_EL_CLIENT" ]; then + execution_layer="$ETH2_EL_CLIENT" + else + execution_layer="geth" + fi + + if [ -n "$PYROSCOPE_SERVER" ]; then + pyroscope_enabled=true + else + pyroscope_enabled=false + fi + + cat << EOF > config.toml + [Network] + selected_networks=$selected_networks + + [ChainlinkImage] + image="$CHAINLINK_IMAGE" + version="$CHAINLINK_VERSION" + + [Pyroscope] + enabled=$pyroscope_enabled + server_url="$PYROSCOPE_SERVER" + environment="$PYROSCOPE_ENVIRONMENT" + key="$PYROSCOPE_KEY" + + [PrivateEthereumNetwork] + consensus_type="pos" + consensus_layer="prysm" + execution_layer="$execution_layer" + wait_for_finalization=false + + [PrivateEthereumNetwork.EthereumChainConfig] + chain_id=1337 + genesis_delay=15 + seconds_per_slot=3 + validator_count=8 + slots_per_epoch=2 + addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] + EOF + + BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + touch .root_dir + - name: Run Tests + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@912bed7e07a1df4d06ea53a031e9773bb65dc7bd # v2.3.0 with: - test_command_to_run: ./tests -test.timeout 30m -test.run ${{ matrix.test }} + test_command_to_run: ./tests -test.timeout ${{ matrix.timeout }} -test.run ${{ matrix.test }} binary_name: tests cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ github.sha }} @@ -207,7 +280,7 @@ jobs: "type": "section", "text": { "type": "mrkdwn", - "text": "${{ contains(join(needs.*.result, ','), 'failure') && 'Some tests failed, notifying <@U01Q4N37KFG> and <@U060CGGPY8H>' || 'All Good!' }}" + "text": "${{ contains(join(needs.*.result, ','), 'failure') && 'Some tests failed, notifying <@U060CGGPY8H>' || 'All Good!' }}" } }, { diff --git a/.github/workflows/integration-chaos-tests.yml b/.github/workflows/integration-chaos-tests.yml index 10c62810996..82af083543e 100644 --- a/.github/workflows/integration-chaos-tests.yml +++ b/.github/workflows/integration-chaos-tests.yml @@ -12,7 +12,6 @@ env: ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:${{ github.sha }} TEST_SUITE: chaos TEST_ARGS: -test.timeout 1h - SELECTED_NETWORKS: SIMULATED CHAINLINK_COMMIT_SHA: ${{ github.sha }} CHAINLINK_ENV_USER: ${{ github.actor }} TEST_LOG_LEVEL: debug @@ -108,6 +107,24 @@ jobs: continue-on-error: true - name: Checkout the repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Prepare Base64 TOML config + env: + CHAINLINK_VERSION: ${{ github.sha }} + run: | + echo ::add-mask::$CHAINLINK_IMAGE + + cat << EOF > config.toml + [Network] + selected_networks=["SIMULATED"] + + [ChainlinkImage] + image="$CHAINLINK_IMAGE" + version="$CHAINLINK_VERSION" + EOF + + BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16 with: diff --git a/.github/workflows/integration-staging-tests.yml b/.github/workflows/integration-staging-tests.yml index 2abb9a3cfae..24e4acfe0fb 100644 --- a/.github/workflows/integration-staging-tests.yml +++ b/.github/workflows/integration-staging-tests.yml @@ -1,3 +1,4 @@ +# NEEDS ADJUSTING TO TOML CONFIG BEFORE USING!! name: E2E Functions staging tests on: @@ -41,18 +42,86 @@ jobs: env: LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_TOKEN: ${{ secrets.LOKI_TOKEN }} - SELECTED_NETWORKS: ${{ inputs.network }} SELECTED_TEST: ${{ inputs.test_type }} MUMBAI_URLS: ${{ secrets.FUNCTIONS_STAGING_MUMBAI_URLS }} MUMBAI_KEYS: ${{ secrets.FUNCTIONS_STAGING_MUMBAI_KEYS }} - WASP_LOG_LEVEL: info steps: - name: Checkout code uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: fetch-depth: 0 + - name: Prepare Base64 TOML override + env: + PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} + PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-sepolia + PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} + run: | + convert_to_toml_array() { + local IFS=',' + local input_array=($1) + local toml_array_format="[" + + for element in "${input_array[@]}"; do + toml_array_format+="\"$element\"," + done + + toml_array_format="${toml_array_format%,}]" + echo "$toml_array_format" + } + + if [ -n "$PYROSCOPE_SERVER" ]; then + pyroscope_enabled=true + else + pyroscope_enabled=false + fi + + cat << EOF > config.toml + [Common] + chainlink_node_funding=0.5 + + [ChainlinkImage] + image="$CHAINLINK_IMAGE" + version="${{ github.sha }}" + + [Pyroscope] + enabled=$pyroscope_enabled + server_url="$PYROSCOPE_SERVER" + environment="$PYROSCOPE_ENVIRONMENT" + key="$PYROSCOPE_KEY" + + [Logging] + run_id="$RUN_ID" + + [Logging.LogStream] + log_targets=$log_targets + + [Logging.Loki] + tenant_id="$LOKI_TENANT_ID" + endpoint="$LOKI_URL" + basic_auth="$LOKI_BASIC_AUTH" + + [Logging.Grafana] + base_url="$GRAFANA_URL" + dasboard_url="/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + + [Network] + selected_networks=["sepolia"] + + [Network.RpcHttpUrls] + sepolia = $(convert_to_toml_array "$SEPOLIA_HTTP_URLS") + + [Network.RpcWsUrls] + sepolia = $(convert_to_toml_array "$SEPOLIA_URLS") + + [Network.WalletKeys] + sepolia = $(convert_to_toml_array "$EVM_KEYS") + EOF + + BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - name: Run E2E soak tests run: | cd integration-tests/load/functions diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index e53d1a11bbb..3ea98ddd8ce 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -97,7 +97,7 @@ jobs: run: | cd ./integration-tests go build ./... - SELECTED_NETWORKS=SIMULATED go test -run=^# ./... + go test -run=^# ./... - name: Lint Go uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0 with: @@ -121,9 +121,9 @@ jobs: - name: "" dockerfile: core/chainlink.Dockerfile tag-suffix: "" - - name: (plugins) - dockerfile: plugins/chainlink.Dockerfile - tag-suffix: -plugins + # - name: (plugins) + # dockerfile: plugins/chainlink.Dockerfile + # tag-suffix: -plugins name: Build Chainlink Image ${{ matrix.image.name }} runs-on: ubuntu20.04-16cores-64GB needs: [changes, enforce-ctf-version] @@ -277,21 +277,28 @@ jobs: else echo "run_command=./smoke/${{ matrix.product.name }}_test.go" >> "$GITHUB_OUTPUT" fi + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + selectedNetworks: ${{ env.SELECTED_NETWORKS }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ${{ matrix.product.pyroscope_env }} + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + ## Run this step when changes that require tests to be run are made - name: Run Tests if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@ea889b3133bd7f16ab19ba4ba130de5d9162c669 # v2.3.4 - env: - PYROSCOPE_SERVER: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }} - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} - LOKI_URL: ${{ secrets.LOKI_URL }} - LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - LOGSTREAM_LOG_TARGETS: ${{ vars.LOGSTREAM_LOG_TARGETS }} - GRAFANA_URL: ${{ vars.GRAFANA_URL }} - GRAFANA_DATASOURCE: ${{ vars.GRAFANA_DATASOURCE }} - RUN_ID: ${{ github.run_id }} with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download @@ -356,14 +363,27 @@ jobs: else echo "run_command=./smoke/${{ matrix.product.name }}_test.go" >> "$GITHUB_OUTPUT" fi + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + selectedNetworks: ${{ env.SELECTED_NETWORKS }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ${{ matrix.product.pyroscope_env }} + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" ## Run this step when changes that require tests to be run are made - name: Run Tests if: needs.changes.outputs.src == 'true' uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16 - env: - PYROSCOPE_SERVER: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }} - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download @@ -401,19 +421,21 @@ jobs: - name: cron nodes: 2 os: ubuntu-latest - pyroscope_env: "" + pyroscope_env: "ci-smoke-cron-evm-simulated" - name: flux nodes: 1 os: ubuntu-latest - pyroscope_env: "" + pyroscope_env: "ci-smoke-flux-evm-simulated" - name: ocr nodes: 2 os: ubuntu-latest + run: -run TestOCRJobReplacement file: ocr pyroscope_env: ci-smoke-ocr-evm-simulated - name: ocr2 nodes: 6 os: ubuntu-latest + run: -run TestOCRv2JobReplacement file: ocr2 pyroscope_env: ci-smoke-ocr2-evm-simulated - name: ocr2 @@ -421,10 +443,6 @@ jobs: os: ubuntu-latest pyroscope_env: ci-smoke-ocr2-plugins-evm-simulated tag_suffix: "-plugins" - - name: runlog - nodes: 1 - os: ubuntu-latest - pyroscope_env: "" - name: vrf nodes: 2 os: ubuntu-latest @@ -523,21 +541,27 @@ jobs: if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' run: | docker logs otel-collector + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + selectedNetworks: ${{ env.SELECTED_NETWORKS }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ${{ matrix.product.pyroscope_env }} + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" ## Run this step when changes that require tests to be run are made - name: Run Tests if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@ea889b3133bd7f16ab19ba4ba130de5d9162c669 # v2.3.4 - env: - PYROSCOPE_SERVER: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }} - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} - LOKI_URL: ${{ secrets.LOKI_URL }} - LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - LOGSTREAM_LOG_TARGETS: ${{ vars.LOGSTREAM_LOG_TARGETS }} - GRAFANA_URL: ${{ vars.GRAFANA_URL }} - GRAFANA_DATASOURCE: ${{ vars.GRAFANA_DATASOURCE }} - RUN_ID: ${{ github.run_id }} + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16 with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download @@ -554,7 +578,7 @@ jobs: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: "" - ## Run this step when changes that do not need the test to run are made + # Run this step when changes that do not need the test to run are made - name: Run Setup if: needs.changes.outputs.src == 'false' uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@ea889b3133bd7f16ab19ba4ba130de5d9162c669 # v2.3.4 @@ -592,6 +616,7 @@ jobs: runs-on: ubuntu-latest name: ETH Smoke Tests needs: [eth-smoke-tests-matrix, eth-smoke-tests-matrix-automation] + # needs: [eth-smoke-tests-matrix] steps: - name: Check smoke test matrix status if: needs.eth-smoke-tests-matrix.result != 'success' || needs.eth-smoke-tests-matrix-automation.result != 'success' @@ -697,6 +722,14 @@ jobs: - name: Name Versions run: | echo "Running migration tests from version '${{ steps.get_latest_version.outputs.latest_version }}' to: '${{ github.sha }}'" + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-upgrade-config + with: + selectedNetworks: ${{ env.SELECTED_NETWORKS }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ steps.get_latest_version.outputs.latest_version }} + upgradeImage: ${{ env.UPGRADE_IMAGE }} + upgradeVersion: ${{ env.UPGRADE_VERSION }} - name: Run Migration Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@ea889b3133bd7f16ab19ba4ba130de5d9162c669 # v2.3.4 with: @@ -732,7 +765,7 @@ jobs: test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' continue-on-error: true - ### Solana Section + ## Solana Section get_solana_sha: name: Get Solana Sha From Go Mod environment: Integration diff --git a/.github/workflows/live-testnet-tests.yml b/.github/workflows/live-testnet-tests.yml index a4c0c244f03..9e12089531d 100644 --- a/.github/workflows/live-testnet-tests.yml +++ b/.github/workflows/live-testnet-tests.yml @@ -32,40 +32,6 @@ env: CHAINLINK_COMMIT_SHA: ${{ github.sha }} CHAINLINK_ENV_USER: ${{ github.actor }} TEST_LOG_LEVEL: debug - EVM_KEYS: ${{ secrets.QA_EVM_KEYS }} - - SEPOLIA_URLS: ${{ secrets.QA_SEPOLIA_URLS }} - SEPOLIA_HTTP_URLS: ${{ secrets.QA_SEPOLIA_HTTP_URLS }} - - BSC_TESTNET_URLS: ${{ secrets.QA_BSC_TESTNET_URLS }} - BSC_TESTNET_HTTP_URLS: ${{ secrets.QA_BSC_TESTNET_HTTP_URLS }} - - OPTIMISM_SEPOLIA_URLS: ${{ secrets.QA_OPTIMISM_SEPOLIA_URLS }} - OPTIMISM_SEPOLIA_HTTP_URLS: ${{ secrets.QA_OPTIMISM_SEPOLIA_HTTP_URLS }} - - ARBITRUM_SEPOLIA_URLS: ${{ secrets.QA_ARBITRUM_SEPOLIA_URLS }} - ARBITRUM_SEPOLIA_HTTP_URLS: ${{ secrets.QA_ARBITRUM_SEPOLIA_HTTP_URLS }} - - BASE_SEPOLIA_URLS: ${{ secrets.QA_BASE_SEPOLIA_URLS }} - BASE_SEPOLIA_HTTP_URLS: ${{ secrets.QA_BASE_SEPOLIA_HTTP_URLS }} - - POLYGON_MUMBAI_URLS: ${{ secrets.QA_POLYGON_MUMBAI_URLS }} - POLYGON_MUMBAI_HTTP_URLS: ${{ secrets.QA_POLYGON_MUMBAI_HTTP_URLS }} - - AVALANCHE_FUJI_URLS: ${{ secrets.QA_AVALANCHE_FUJI_URLS }} - AVALANCHE_FUJI_HTTP_URLS: ${{ secrets.QA_AVALANCHE_FUJI_HTTP_URLS }} - - FANTOM_TESTNET_URLS: ${{ secrets.QA_FANTOM_TESTNET_URLS }} - FANTOM_TESTNET_HTTP_URLS: ${{ secrets.QA_FANTOM_TESTNET_HTTP_URLS }} - - CELO_ALFAJORES_URLS: ${{ secrets.QA_CELO_ALFAJORES_URLS }} - CELO_ALFAJORES_HTTP_URLS: ${{ secrets.QA_CELO_ALFAJORES_HTTP_URLS }} - - SCROLL_SEPOLIA_URLS: ${{ secrets.QA_SCROLL_SEPOLIA_URLS }} - SCROLL_SEPOLIA_HTTP_URLS: ${{ secrets.QA_SCROLL_SEPOLIA_HTTP_URLS }} - - LINEA_GOERLI_URLS: ${{ secrets.QA_LINEA_GOERLI_URLS }} - LINEA_GOERLI_HTTP_URLS: ${{ secrets.QA_LINEA_GOERLI_HTTP_URLS }} jobs: @@ -107,7 +73,7 @@ jobs: permissions: id-token: write contents: read - name: Build Tests Binary + name: Build Tests Binary runs-on: ubuntu-latest steps: - name: Collect Metrics @@ -128,6 +94,7 @@ jobs: test_download_vendor_packages_command: cd ./integration-tests && go mod download token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod + go_tags: embed cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "true" binary_name: tests @@ -237,8 +204,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: SEPOLIA strategy: max-parallel: 1 fail-fast: false @@ -253,16 +218,35 @@ jobs: name: Sepolia ${{ matrix.product }} Tests runs-on: ubuntu-latest steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-sepolia + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "sepolia" + httpEndpoints: ${{ secrets.QA_SEPOLIA_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_SEPOLIA_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: - name: tests + name: tests - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-sepolia - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests @@ -292,8 +276,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: BSC_TESTNET strategy: max-parallel: 1 fail-fast: false @@ -307,17 +289,36 @@ jobs: test: TestAutomationBasic/registry_2_1_logtrigger name: BSC Testnet ${{ matrix.product }} Tests runs-on: ubuntu-latest - steps: + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-bsc-testnet + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "bsc_testnet" + httpEndpoints: ${{ secrets.QA_BSC_TESTNET_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_BSC_TESTNET_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: - name: tests - - name: Run Tests + name: tests + - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-bsc-testnet - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests @@ -345,8 +346,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: OPTIMISM_SEPOLIA strategy: max-parallel: 1 fail-fast: false @@ -361,16 +360,35 @@ jobs: name: Optimism Sepolia ${{ matrix.product }} Tests runs-on: ubuntu-latest steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-optimism-sepolia + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "optimism_sepolia" + httpEndpoints: ${{ secrets.QA_OPTIMISM_SEPOLIA_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_OPTIMISM_SEPOLIA_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: - name: tests + name: tests - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-optimism-sepolia - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests @@ -398,8 +416,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: ARBITRUM_SEPOLIA strategy: max-parallel: 1 fail-fast: false @@ -414,16 +430,35 @@ jobs: name: Arbitrum Sepolia ${{ matrix.product }} Tests runs-on: ubuntu-latest steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-arbitrum-sepolia + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "arbitrum_sepolia" + httpEndpoints: ${{ secrets.QA_ARBITRUM_SEPOLIA_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_ARBITRUM_SEPOLIA_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: tests - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-arbitrum-sepolia - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests @@ -451,8 +486,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: BASE_SEPOLIA strategy: max-parallel: 1 fail-fast: false @@ -463,16 +496,35 @@ jobs: name: Base Sepolia ${{ matrix.product }} Tests runs-on: ubuntu-latest steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-base-sepolia + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "base_sepolia" + httpEndpoints: ${{ secrets.QA_BASE_SEPOLIA_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_BASE_SEPOLIA_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: tests - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-base-sepolia - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests @@ -500,8 +552,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: POLYGON_MUMBAI strategy: max-parallel: 1 fail-fast: false @@ -516,16 +566,35 @@ jobs: name: Polygon Mumbai ${{ matrix.product }} Tests runs-on: ubuntu-latest steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-polygon-mumbai + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "polygon_mumbai" + httpEndpoints: ${{ secrets.QA_POLYGON_MUMBAI_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_POLYGON_MUMBAI_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: tests - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-polygon-mumbai - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests @@ -553,8 +622,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: AVALANCHE_FUJI strategy: max-parallel: 1 fail-fast: false @@ -569,16 +636,35 @@ jobs: name: Avalanche Fuji ${{ matrix.product }} Tests runs-on: ubuntu-latest steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-avalanche-fuji + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "avalanche_fuji" + httpEndpoints: ${{ secrets.QA_AVALANCHE_FUJI_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_AVALANCHE_FUJI_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: tests - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-avalanche-fuji - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests @@ -606,8 +692,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: FANTOM_TESTNET strategy: max-parallel: 1 fail-fast: false @@ -622,16 +706,35 @@ jobs: name: Fantom Testnet ${{ matrix.product }} Tests runs-on: ubuntu-latest steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-fantom-testnet + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "fantom_testnet" + httpEndpoints: ${{ secrets.QA_FANTOM_TESTNET_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_FANTOM_TESTNET_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: tests - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-fantom-testnet - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests @@ -659,8 +762,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: CELO_ALFAJORES strategy: max-parallel: 1 fail-fast: false @@ -671,16 +772,35 @@ jobs: name: Celo Alfajores ${{ matrix.product }} Tests runs-on: ubuntu-latest steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-celo-alfajores + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "celo_alfajores" + httpEndpoints: ${{ secrets.QA_CELO_ALFAJORES_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_CELO_ALFAJORES_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: tests - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-celo-alfajores - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests @@ -710,8 +830,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: SCROLL_SEPOLIA strategy: max-parallel: 1 fail-fast: false @@ -722,16 +840,35 @@ jobs: name: Scroll Sepolia ${{ matrix.product }} Tests runs-on: ubuntu-latest steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-scroll-sepolia + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "scroll_sepolia" + httpEndpoints: ${{ secrets.QA_SCROLL_SEPOLIA_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_SCROLL_SEPOLIA_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: - name: tests + name: tests - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-scroll-sepolia - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests @@ -759,8 +896,6 @@ jobs: id-token: write contents: read needs: [build-chainlink, build-tests] - env: - SELECTED_NETWORKS: LINEA_GOERLI strategy: max-parallel: 1 fail-fast: false @@ -771,16 +906,35 @@ jobs: name: Linea Goerli ${{ matrix.product }} Tests runs-on: ubuntu-latest steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config-live-testnets + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-linea-goerli + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: ${{ secrets.LOKI_URL }} + lokiTenantId: ${{ vars.LOKI_TENANT_ID }} + lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + network: "linea_goerli" + httpEndpoints: ${{ secrets.QA_LINEA_GOERLI_HTTP_URLS }} + wsEndpoints: ${{ secrets.QA_LINEA_GOERLI_URLS }} + fundingKeys: ${{ secrets.QA_EVM_KEYS }} - name: Download Tests Binary uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: - name: tests + name: tests - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@952abab6367aaff96102abf9ef751ef36fe9ea29 # v2.3.3 - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-linea-goerli - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} with: test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} binary_name: tests diff --git a/.github/workflows/on-demand-log-poller.yml b/.github/workflows/on-demand-log-poller.yml index 4b2d67bcf9a..ad3617841d3 100644 --- a/.github/workflows/on-demand-log-poller.yml +++ b/.github/workflows/on-demand-log-poller.yml @@ -2,80 +2,26 @@ name: On Demand Log Poller Consistency Test on: workflow_dispatch: inputs: - contracts: - description: Number of test contracts - default: "2" + base64Config: + description: base64-ed config required: true - eventsPerTx: - description: Number of events to emit per transaction - default: "10" - required: true - useFinalityTag: - description: Use finality tag - default: "false" - required: true - loadDuration: - description: Load duration (e.g. 10s, 10m, 1h) - default: "10m" - required: true - chainlinkImage: - description: Chainlink image to use - default: "public.ecr.aws/chainlink/chainlink" - required: true - chainlinkVersion: - description: Chainlink version to use - default: "2.7.0-beta1" - required: true - selectedNetworks: - type: choice - description: Networks to test on - options: - - "SIMULATED" - - "SEPOLIA" - - "MUMBAI" - fundingPrivateKey: - description: Private funding key (Skip for Simulated) - required: false - type: string - wsURL: - description: WS URL for the network (Skip for Simulated) - required: false type: string - httpURL: - description: HTTP URL for the network (Skip for Simulated) - required: false - type: string jobs: test: env: - CONTRACTS: ${{ inputs.contracts }} - EVENTS_PER_TX: ${{ inputs.eventsPerTx }} - LOAD_DURATION: ${{ inputs.loadDuration }} - USE_FINALITY_TAG: ${{ inputs.useFinalityTag }} - CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} - CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} - SELECTED_NETWORKS: ${{ inputs.selectedNetworks }} REF_NAME: ${{ github.head_ref || github.ref_name }} runs-on: ubuntu20.04-8cores-32GB steps: - - name: Get Inputs + - name: Add masks and export base64 config run: | - EVM_URLS=$(jq -r '.inputs.wsURL' $GITHUB_EVENT_PATH) - EVM_HTTP_URLS=$(jq -r '.inputs.httpURL' $GITHUB_EVENT_PATH) - EVM_KEYS=$(jq -r '.inputs.fundingPrivateKey' $GITHUB_EVENT_PATH) - - echo ::add-mask::$EVM_URLS - echo ::add-mask::$EVM_HTTP_URLS - echo ::add-mask::$EVM_KEYS - - echo EVM_URLS=$EVM_URLS >> $GITHUB_ENV - echo EVM_HTTP_URLS=$EVM_HTTP_URLS >> $GITHUB_ENV - echo EVM_KEYS=$EVM_KEYS >> $GITHUB_ENV + BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - name: Checkout the repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: - ref: ${{ env.REF_NAME }} + ref: ${{ env.REF_NAME }} - name: Setup Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml index 32e080aafca..b02e44db117 100644 --- a/.github/workflows/on-demand-ocr-soak-test.yml +++ b/.github/workflows/on-demand-ocr-soak-test.yml @@ -2,74 +2,19 @@ name: On Demand OCR Soak Test on: workflow_dispatch: inputs: - network: - description: Network to run tests on - type: choice - options: - - "SIMULATED" - - "GOERLI" - - "OPTIMISM_GOERLI" - - "ARBITRUM_GOERLI" - - "ARBITRUM_SEPOLIA" - - "ARBITRUM_MAINNET" - - "CELO_ALFAJORES" - - "CELO_MAINNET" - - "BASE_GOERLI" - - "BASE_SEPOLIA" - - "BASE_MAINNET" - - "BSC_MAINNET" - - "BSC_TESTNET" - - "SCROLL_SEPOLIA" - - "SCROLL_MAINNET" - - "POLYGON_MUMBAI" - - "POLYGON_MAINNET" - - "LINEA_GOERLI" - - "LINEA_MAINNET" - - "FANTOM_TESTNET" - - "FANTOM_MAINNET" - - "KROMA_MAINNET" - - "KROMA_SEPOLIA" - - "WEMIX_TESTNET" - - "WEMIX_MAINNET" - fundingPrivateKey: - description: Private funding key (Skip for Simulated) - required: false - type: string - wsURL: - description: WS URL for the network (Skip for Simulated) - required: false - type: string - httpURL: - description: HTTP URL for the network (Skip for Simulated) - required: false - type: string + base64Config: + description: base64-ed config + required: true + type: string slackMemberID: description: Slack Member ID (Not your @) required: true default: U01A2B2C3D4 type: string - chainlinkImage: - description: Container image location for the Chainlink nodes - required: true - default: public.ecr.aws/chainlink/chainlink - chainlinkVersion: - description: Container image version for the Chainlink nodes - required: true - default: "2.7.0" - ocrVersion: - description: Version of OCR to Use - type: choice - options: - - 1 - - 2 - testInputs: - description: Duration;Funding;TimeBetweenRounds - required: false - default: "10m;.1;1m" jobs: ocr_soak_test: - name: ${{ inputs.network }} OCR Soak Test + name: OCR Soak Test environment: integration runs-on: ubuntu-latest permissions: @@ -78,12 +23,9 @@ jobs: id-token: write contents: read env: - CHAINLINK_COMMIT_SHA: ${{ inputs.chainlinkVersion }} CHAINLINK_ENV_USER: ${{ github.actor }} - SELECTED_NETWORKS: ${{ inputs.network }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} SLACK_CHANNEL: ${{ secrets.QA_SLACK_CHANNEL }} - OCR_VERSION: ${{ inputs.ocrVersion }} TEST_LOG_LEVEL: debug REF_NAME: ${{ github.head_ref || github.ref_name }} ENV_JOB_IMAGE_BASE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests @@ -96,54 +38,32 @@ jobs: hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} this-job-name: ${{ inputs.network }} OCR Soak Test continue-on-error: true - - name: Get Inputs + - name: Checkout the repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ env.REF_NAME }} + - name: Get Slack config and mask base64 config run: | - # Mask the sensitive inputs - EVM_URLS=$(jq -r '.inputs.wsURL' $GITHUB_EVENT_PATH) - EVM_HTTP_URLS=$(jq -r '.inputs.httpURL' $GITHUB_EVENT_PATH) - EVM_KEYS=$(jq -r '.inputs.fundingPrivateKey' $GITHUB_EVENT_PATH) SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH) - - echo ::add-mask::$EVM_URLS - echo ::add-mask::$EVM_HTTP_URLS - echo ::add-mask::$EVM_KEYS echo ::add-mask::$SLACK_USER - - echo EVM_URLS=$EVM_URLS >> $GITHUB_ENV - echo EVM_HTTP_URLS=$EVM_HTTP_URLS >> $GITHUB_ENV - echo EVM_KEYS=$EVM_KEYS >> $GITHUB_ENV echo SLACK_USER=$SLACK_USER >> $GITHUB_ENV - # Read in our test inputs - IFS=';' read -ra parts <<< "${{ inputs.testInputs }}" - index=0 - for part in "${parts[@]}"; do - # A little hacky, but good enough for this - if [ $index -eq 0 ]; then - echo "OCR_TEST_DURATION=$part" - echo "OCR_TEST_DURATION=$part" >> $GITHUB_ENV - elif [ $index -eq 1 ]; then - echo "OCR_CHAINLINK_NODE_FUNDING=$part" - echo "OCR_CHAINLINK_NODE_FUNDING=$part" >> $GITHUB_ENV - elif [ $index -eq 2 ]; then - echo "OCR_TIME_BETWEEN_ROUNDS=$part" - echo "OCR_TIME_BETWEEN_ROUNDS=$part" >> $GITHUB_ENV - else - echo "Additional Unregistered Input: $part" - fi - ((index+=1)) - done - - name: Checkout the repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + - name: Parse base64 config + uses: ./.github/actions/setup-parse-base64-config with: - ref: ${{ env.REF_NAME }} + base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} - name: Setup Push Tag shell: bash run: | echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY + echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - name: Build Image uses: ./.github/actions/build-test-image with: @@ -163,8 +83,8 @@ jobs: with: test_command_to_run: cd ./integration-tests && go test -v -count=1 -run ^TestOCRSoak$ ./soak test_download_vendor_packages_command: make gomod - cl_repo: ${{ inputs.chainlinkImage }} - cl_image_tag: ${{ inputs.chainlinkVersion }} + cl_repo: ${{ env.CHAINLINK_IMAGE }} + cl_image_tag: ${{ env.CHAINLINK_VERSION }} token: ${{ secrets.GITHUB_TOKEN }} should_cleanup: false go_mod_path: ./integration-tests/go.mod diff --git a/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml b/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml index 3b27e4519c8..de53b493a5f 100644 --- a/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml +++ b/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml @@ -2,28 +2,14 @@ name: On Demand VRFV2 Smoke Test (Ethereum clients) on: workflow_dispatch: inputs: - client: - description: Execution client to use - type: choice - options: - - "geth" - - "nethermind" - - "besu" - - "erigon" - chainlinkImage: - description: Container image location for the Chainlink nodes + base64Config: + description: base64-ed config required: true - default: public.ecr.aws/chainlink/chainlink - chainlinkVersion: - description: Container image version for the Chainlink nodes - required: true - default: "2.6.0" - configBase64: - description: TOML config in base64 (Needed when overriding config or providing contract addresses for existing env) - required: false + type: string + jobs: vrfv2_smoke_test: - name: VRFV2 Smoke Test with ${{ inputs.client }} client + name: VRFV2 Smoke Test with custom EL client client environment: integration runs-on: ubuntu20.04-8cores-32GB permissions: @@ -32,31 +18,40 @@ jobs: id-token: write contents: read env: - SELECTED_NETWORKS: "SIMULATED" - CONFIG: ${{ inputs.configBase64 }} TEST_LOG_LEVEL: debug REF_NAME: ${{ github.head_ref || github.ref_name }} - CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} - CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} steps: - - name: Setup Push Tag + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Mask base64 config + run: | + BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + - name: Parse base64 config + uses: ./.github/actions/setup-parse-base64-config + with: + base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} + - name: Send details to Step Summary shell: bash run: | echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - - name: Checkout code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - fetch-depth: 0 + echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY + echo "### Execution client used" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.ETH2_EL_CLIENT }}\`" >>$GITHUB_STEP_SUMMARY - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15 with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -run TestVRFv2Basic ./smoke/vrfv2_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ inputs.chainlinkImage }} - cl_image_tag: ${{ inputs.chainlinkVersion }} + cl_repo: ${{ env.CHAINLINK_IMAGE }} + cl_image_tag: ${{ env.CHAINLINK_VERSION }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} artifacts_name: vrf-test-logs artifacts_location: ./integration-tests/smoke/logs/ @@ -66,5 +61,3 @@ jobs: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: "" - env: - ETH2_EL_CLIENT: ${{ inputs.client }} diff --git a/.github/workflows/on-demand-vrfv2-performance-test.yml b/.github/workflows/on-demand-vrfv2-performance-test.yml index 3c505ed24ff..7fd0d2b83b1 100644 --- a/.github/workflows/on-demand-vrfv2-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2-performance-test.yml @@ -2,45 +2,10 @@ name: On Demand VRFV2 Performance Test on: workflow_dispatch: inputs: - network: - description: Network to run tests on - type: choice - options: - - "ETHEREUM_MAINNET" - - "SIMULATED" - - "SEPOLIA" - - "OPTIMISM_MAINNET" - - "OPTIMISM_GOERLI" - - "ARBITRUM_MAINNET" - - "ARBITRUM_GOERLI" - - "ARBITRUM_SEPOLIA" - - "BSC_MAINNET" - - "BSC_TESTNET" - - "POLYGON_MAINNET" - - "POLYGON_MUMBAI" - - "AVALANCHE_FUJI" - - "AVALANCHE_MAINNET" - - "NEXON_DEV" - fundingPrivateKey: - description: Private funding key (Skip for Simulated) - required: false - type: string - wsURL: - description: WS URL for the network (Skip for Simulated) - required: false - type: string - httpURL: - description: HTTP URL for the network (Skip for Simulated) - required: false - type: string - chainlinkImage: - description: Container image location for the Chainlink nodes + base64Config: + description: base64-ed config required: true - default: public.ecr.aws/chainlink/chainlink - chainlinkVersion: - description: Container image version for the Chainlink nodes - required: true - default: "2.6.0" + type: string performanceTestType: description: Performance Test Type of test to run type: choice @@ -49,20 +14,9 @@ on: - "Load" - "Stress" - "Spike" - testDuration: - description: Duration of the test (time string) - required: true - default: 5m - useExistingEnv: - description: Set `true` to use existing environment or `false` to deploy CL node and all contracts - required: false - default: false - configBase64: - description: TOML config in base64 (Needed when overriding config or providing contract addresses for existing env) - required: false jobs: vrfv2_performance_test: - name: ${{ inputs.network }} VRFV2 Performance Test + name: VRFV2 Performance Test environment: integration runs-on: ubuntu20.04-8cores-32GB permissions: @@ -74,15 +28,9 @@ jobs: LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - SELECTED_NETWORKS: ${{ inputs.network }} TEST_TYPE: ${{ inputs.performanceTestType }} - VRFV2_TEST_DURATION: ${{ inputs.testDuration }} - VRFV2_USE_EXISTING_ENV: ${{ inputs.useExistingEnv }} - CONFIG: ${{ inputs.configBase64 }} TEST_LOG_LEVEL: debug REF_NAME: ${{ github.head_ref || github.ref_name }} - CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} - CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} SLACK_CHANNEL: ${{ secrets.QA_VRF_SLACK_CHANNEL }} WASP_LOG_LEVEL: info @@ -95,38 +43,35 @@ jobs: hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} this-job-name: ${{ inputs.network }} VRFV2 Performance Test continue-on-error: true - - name: Setup Push Tag + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Mask base64 config + run: | + BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + - name: Merge and export base64 config + uses: ./.github/actions/setup-merge-base64-config + with: + base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} + - name: Send details to Step Summary shell: bash run: | echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - - name: Get Inputs - run: | - EVM_URLS=$(jq -r '.inputs.wsURL' $GITHUB_EVENT_PATH) - EVM_HTTP_URLS=$(jq -r '.inputs.httpURL' $GITHUB_EVENT_PATH) - EVM_KEYS=$(jq -r '.inputs.fundingPrivateKey' $GITHUB_EVENT_PATH) - - echo ::add-mask::$EVM_URLS - echo ::add-mask::$EVM_HTTP_URLS - echo ::add-mask::$EVM_KEYS - - echo EVM_URLS=$EVM_URLS >> $GITHUB_ENV - echo EVM_HTTP_URLS=$EVM_HTTP_URLS >> $GITHUB_ENV - echo EVM_KEYS=$EVM_KEYS >> $GITHUB_ENV - - - name: Checkout code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - fetch-depth: 0 + echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15 with: test_command_to_run: cd ./integration-tests && go test -v -count=1 -timeout 24h -run TestVRFV2Performance/vrfv2_performance_test ./load/vrfv2 test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ inputs.chainlinkImage }} - cl_image_tag: ${{ inputs.chainlinkVersion }} + cl_repo: ${{ env.CHAINLINK_IMAGE }} + cl_image_tag: ${{ env.CHAINLINK_VERSION }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} artifacts_name: vrf-test-logs artifacts_location: ./integration-tests/load/vrfv2/logs/ diff --git a/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml b/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml index 331c626ba9c..1772730075e 100644 --- a/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml +++ b/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml @@ -2,28 +2,14 @@ name: On Demand VRFV2Plus Smoke Test (Ethereum clients) on: workflow_dispatch: inputs: - client: - description: Execution client to use - type: choice - options: - - "geth" - - "nethermind" - - "besu" - - "erigon" - chainlinkImage: - description: Container image location for the Chainlink nodes + base64Config: + description: base64-ed config required: true - default: public.ecr.aws/chainlink/chainlink - chainlinkVersion: - description: Container image version for the Chainlink nodes - required: true - default: "2.6.0" - configBase64: - description: TOML config in base64 (Needed when overriding config or providing contract addresses for existing env) - required: false + type: string + jobs: vrfv2plus_smoke_test: - name: VRFV2Plus Smoke Test with ${{ inputs.client }} client + name: VRFV2Plus Smoke Test with custom EL client environment: integration runs-on: ubuntu20.04-8cores-32GB permissions: @@ -32,31 +18,40 @@ jobs: id-token: write contents: read env: - SELECTED_NETWORKS: "SIMULATED" - CONFIG: ${{ inputs.configBase64 }} TEST_LOG_LEVEL: debug REF_NAME: ${{ github.head_ref || github.ref_name }} - CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} - CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} - steps: - - name: Setup Push Tag + steps: + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Mask base64 config + run: | + BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + - name: Parse base64 config + uses: ./.github/actions/setup-parse-base64-config + with: + base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} + - name: Send details to Step Summary shell: bash run: | echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - - name: Checkout code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - fetch-depth: 0 + echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY + echo "### Execution client used" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.ETH2_EL_CLIENT }}\`" >>$GITHUB_STEP_SUMMARY - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7d541cbbca52d45b8a718257af86d9cf49774d1f # v2.2.15 with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -run ^TestVRFv2Plus$/^Link_Billing$ ./smoke/vrfv2plus_test.go 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ inputs.chainlinkImage }} - cl_image_tag: ${{ inputs.chainlinkVersion }} + cl_repo: ${{ env.CHAINLINK_IMAGE }} + cl_image_tag: ${{ env.CHAINLINK_VERSION }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} artifacts_name: vrfplus-test-logs artifacts_location: ./integration-tests/smoke/logs/ @@ -66,5 +61,3 @@ jobs: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: "" - env: - ETH2_EL_CLIENT: ${{ inputs.client }} diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml index 86c35d8e076..858eecff761 100644 --- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml @@ -2,45 +2,10 @@ name: On Demand VRFV2 Plus Performance Test on: workflow_dispatch: inputs: - network: - description: Network to run tests on - type: choice - options: - - "ETHEREUM_MAINNET" - - "SIMULATED" - - "SEPOLIA" - - "OPTIMISM_MAINNET" - - "OPTIMISM_GOERLI" - - "ARBITRUM_MAINNET" - - "ARBITRUM_GOERLI" - - "ARBITRUM_SEPOLIA" - - "BSC_MAINNET" - - "BSC_TESTNET" - - "POLYGON_MAINNET" - - "POLYGON_MUMBAI" - - "AVALANCHE_FUJI" - - "AVALANCHE_MAINNET" - - "NEXON_DEV" - fundingPrivateKey: - description: Private funding key (Skip for Simulated) - required: false - type: string - wsURL: - description: WS URL for the network (Skip for Simulated) - required: false - type: string - httpURL: - description: HTTP URL for the network (Skip for Simulated) - required: false - type: string - chainlinkImage: - description: Container image location for the Chainlink nodes - required: true - default: public.ecr.aws/chainlink/chainlink - chainlinkVersion: - description: Container image version for the Chainlink nodes + base64Config: + description: base64-ed config required: true - default: "2.6.0" + type: string performanceTestType: description: Performance Test Type of test to run type: choice @@ -48,21 +13,11 @@ on: - "Soak" - "Load" - "Stress" - - "Spike" - testDuration: - description: Duration of the test (time string) - required: true - default: 5m - useExistingEnv: - description: Set `true` to use existing environment or `false` to deploy CL node and all contracts - required: false - default: "false" - configBase64: - description: TOML config in base64 (Needed when overriding config or providing contract addresses for existing env) - required: false + - "Spike" + jobs: vrfv2plus_performance_test: - name: ${{ inputs.network }} VRFV2 Plus Performance Test + name: VRFV2 Plus Performance Test environment: integration runs-on: ubuntu20.04-8cores-32GB permissions: @@ -74,19 +29,13 @@ jobs: LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - SELECTED_NETWORKS: ${{ inputs.network }} TEST_TYPE: ${{ inputs.performanceTestType }} - VRFV2PLUS_TEST_DURATION: ${{ inputs.testDuration }} - VRFV2PLUS_USE_EXISTING_ENV: ${{ inputs.useExistingEnv }} - CONFIG: ${{ inputs.configBase64 }} TEST_LOG_LEVEL: debug REF_NAME: ${{ github.head_ref || github.ref_name }} - CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} - CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} SLACK_CHANNEL: ${{ secrets.QA_VRF_SLACK_CHANNEL }} WASP_LOG_LEVEL: info - steps: + steps: - name: Collect Metrics id: collect-gha-metrics uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2 @@ -95,38 +44,35 @@ jobs: hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} this-job-name: ${{ inputs.network }} VRFV2 Plus Performance Test continue-on-error: true - - name: Setup Push Tag + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - name: Mask base64 config + run: | + BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + - name: Merge and export base64 config + uses: ./.github/actions/setup-merge-base64-config + with: + base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} + - name: Send details to Step Summary shell: bash run: | echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ inputs.chainlinkVersion }}\`" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - - name: Get Inputs - run: | - EVM_URLS=$(jq -r '.inputs.wsURL' $GITHUB_EVENT_PATH) - EVM_HTTP_URLS=$(jq -r '.inputs.httpURL' $GITHUB_EVENT_PATH) - EVM_KEYS=$(jq -r '.inputs.fundingPrivateKey' $GITHUB_EVENT_PATH) - - echo ::add-mask::$EVM_URLS - echo ::add-mask::$EVM_HTTP_URLS - echo ::add-mask::$EVM_KEYS - - echo EVM_URLS=$EVM_URLS >> $GITHUB_ENV - echo EVM_HTTP_URLS=$EVM_HTTP_URLS >> $GITHUB_ENV - echo EVM_KEYS=$EVM_KEYS >> $GITHUB_ENV - - - name: Checkout code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - fetch-depth: 0 + echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16 with: test_command_to_run: cd ./integration-tests && go test -v -count=1 -timeout 24h -run TestVRFV2PlusPerformance/vrfv2plus_performance_test ./load/vrfv2plus test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ inputs.chainlinkImage }} - cl_image_tag: ${{ inputs.chainlinkVersion }} + cl_repo: ${{ env.CHAINLINK_IMAGE }} + cl_image_tag: ${{ env.CHAINLINK_VERSION }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} artifacts_name: vrf-test-logs artifacts_location: ./integration-tests/load/vrfv2plus/logs/ diff --git a/.github/workflows/performance-tests.yml b/.github/workflows/performance-tests.yml deleted file mode 100644 index 7b9eef7fccc..00000000000 --- a/.github/workflows/performance-tests.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: Performance Tests -on: - workflow_dispatch: - inputs: - focus: - description: cron|directrequest|flux|keeper|ocr|vrf|suite - required: true - default: suite - type: string - -jobs: - build-chainlink: - environment: integration - permissions: - id-token: write - contents: read - name: Build Chainlink Image - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1 - with: - aws-region: ${{ secrets.QA_AWS_REGION }} - role-to-assume: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - role-duration-seconds: 3600 - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 - - name: Build and Push - uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 - with: - context: . - file: core/chainlink.Dockerfile - # comma separated like: KEY1=VAL1,KEY2=VAL2,... - build-args: COMMIT_SHA=${{ github.sha }} - tags: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink:latest.${{ github.sha }} - push: true - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2 - with: - basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} - this-job-name: Build Chainlink Image - continue-on-error: true - run_tests: - environment: integration - name: run core evm ${{ github.event.inputs.focus }} performance tests - runs-on: ubuntu-latest - needs: build-chainlink - steps: - - name: Checkout the repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@e865e376b8c2d594028c8d645dd6c47169b72974 # v2.2.16 - with: - test_command_to_run: cd integration-tests && go test -timeout 1h -count=1 -json -test.parallel 10 ./performance 2>&1 | tee /tmp/gotest.log | gotestfmt - test_download_vendor_packages_command: make gomod - cl_repo: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - cl_image_tag: latest.${{ github.sha }} - artifacts_location: ./integration-tests/performance/logs - publish_report_paths: ./tests-perf-report.xml - publish_check_name: Core Performance Test Results - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Publish pprof artifacts - if: ${{ success() }} - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: pprof_results - path: ./integration-tests/performance/logs - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d1618b772a97fd87e6505de97b872ee0b1f1729a # v2.0.2 - with: - basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} - this-job-name: run core evm ${{ github.event.inputs.focus }} performance tests - continue-on-error: true diff --git a/.gitignore b/.gitignore index 45ec5eb2bd4..ae69535d352 100644 --- a/.gitignore +++ b/.gitignore @@ -83,8 +83,12 @@ go.work* # This sometimes shows up for some reason tools/flakeytests/coverage.txt +# Integration tests create these files .test_summary/ .run.id # Fuzz tests can create these files **/testdata/fuzz/* + +# Runtime test configuration that might contain secrets +overrides.toml \ No newline at end of file diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 4ecbf283746..bd13587c679 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1127,8 +1127,8 @@ github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= -github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -1967,8 +1967,8 @@ modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= -nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= diff --git a/go.mod b/go.mod index ab63dbd6475..0bc08adc3fc 100644 --- a/go.mod +++ b/go.mod @@ -266,6 +266,7 @@ require ( github.com/prometheus/procfs v0.12.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect + github.com/rs/zerolog v1.30.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/sethvargo/go-retry v0.2.4 // indirect @@ -321,6 +322,7 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + nhooyr.io/websocket v1.8.7 // indirect pgregory.net/rapid v0.5.5 // indirect rsc.io/tmplfunc v0.0.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/go.sum b/go.sum index b71fcd79bc2..ba26cb877d8 100644 --- a/go.sum +++ b/go.sum @@ -261,6 +261,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= @@ -430,6 +431,7 @@ github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NB github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= @@ -473,12 +475,15 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= @@ -501,6 +506,7 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -846,6 +852,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= @@ -876,6 +883,7 @@ github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awS github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= @@ -1111,10 +1119,11 @@ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUz github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= -github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -1953,8 +1962,8 @@ modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= -nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= diff --git a/integration-tests/.root_dir b/integration-tests/.root_dir new file mode 100644 index 00000000000..e69de29bb2d diff --git a/integration-tests/Makefile b/integration-tests/Makefile index 62d9b281d66..8415c00f9cd 100644 --- a/integration-tests/Makefile +++ b/integration-tests/Makefile @@ -60,12 +60,12 @@ lint: golangci-lint --color=always run ./... --fix -v build: - @go build ./... && SELECTED_NETWORKS=SIMULATED go test -run=^# ./... + @go build ./... go test -run=^# ./... # Builds the test image # tag: the tag for the test image being built, example: tag=tate # base_tag: the tag for the base-test-image to use, example: base_tag=latest -# suite: the test suites to build into the image, example: suite="chaos soak smoke reorg migration performance" +# suite: the test suites to build into the image, example: suite="chaos soak smoke reorg migration" # push: set to true if you want the image pushed or leave blank if not, example: push=true .PHONY: build_test_image build_test_image: @@ -89,10 +89,11 @@ run_tracing: ## Test Runner .PHONY: run -run: # Need to set network first in case it's unset. Doesn't matter for the runner - SELECTED_NETWORKS="SIMULATED" go run . +run: + go run . ## All commands will use 16 threads to run tests in parallel. To change this, use -test.parallel n +## Remember to set selected_networks and CL image in the TOML file (e.g. overrides.toml) # Smoke .PHONY: test_smoke_product @@ -122,23 +123,15 @@ test_chaos_network: install_gotestfmt ## Run all smoke tests test_chaos_verbose: ## Run all smoke tests with verbose logging go test -timeout 24h -count=1 -v $(args) ./chaos -# Performance -.PHONY: test_perf -test_perf: ## Run core node performance tests. - TEST_LOG_LEVEL="disabled" \ - SELECTED_NETWORKS="SIMULATED,SIMULATED_1,SIMULATED_2" \ - go test -timeout 1h -count=1 -json $(args) ./performance 2>&1 | tee /tmp/gotest.log | gotestfmt - # Migrations .PHONY: test_node_migrations -test_node_migrations: install_gotestfmt ## Run all node migration tests +test_node_migrations: install_gotestfmt ## Run all node migration tests. TEST_LOG_LEVEL="disabled" \ go test -timeout 1h -count=1 -json $(args) ./migration 2>&1 | tee /tmp/gotest.log | gotestfmt .PHONY: test_node_migrations_simulated -test_node_migrations_simulated: install_gotestfmt +test_node_migrations_simulated: install_gotestfmt TEST_LOG_LEVEL="disabled" \ - SELECTED_NETWORKS="SIMULATED,SIMULATED_1,SIMULATED_2" \ go test -timeout 1h -count=1 -json $(args) ./migration 2>&1 | tee /tmp/gotest.log | gotestfmt .PHONY: test_node_migrations_verbose @@ -147,7 +140,6 @@ test_node_migrations_verbose: .PHONY: test_node_migrations_simulated_verbose test_node_migrations_simulated_verbose: - SELECTED_NETWORKS="SIMULATED,SIMULATED_1,SIMULATED_2" \ go test -timeout 1h -count=1 -v $(args) ./migration # Soak @@ -157,7 +149,7 @@ test_soak_ocr: .PHONY: test_soak_ocr_simulated test_soak_ocr_simulated: - SELECTED_NETWORKS="SIMULATED" go test -v -count=1 -run TestOCRSoak ./soak + go test -v -count=1 -run TestOCRSoak ./soak .PHONY: test_soak_forwarder_ocr test_soak_forwarder_ocr: @@ -165,7 +157,7 @@ test_soak_forwarder_ocr: .PHONY: test_soak_forwarder_ocr_simulated test_soak_forwarder_ocr_simulated: - SELECTED_NETWORKS="SIMULATED" go test -v -count=1 -run TestForwarderOCRSoak ./soak + go test -v -count=1 -run TestForwarderOCRSoak ./soak .PHONY: test_soak_automation test_soak_automation: @@ -173,8 +165,6 @@ test_soak_automation: .PHONY: test_soak_automation_simulated test_soak_automation_simulated: - SELECTED_NETWORKS="SIMULATED" \ - TEST_INPUTS="TEST_TYPE=SOAK,NUMBEROFCONTRACTS=50,BLOCKRANGE=1000,BLOCKINTERVAL=50,GRAFANA_DASHBOARD_URL=https://chainlinklabs.grafana.net/d/Q8n6m1unz/chainlink-keepers-qa?orgId=1" \ go test -v -run ^TestAutomationBenchmark$$ ./benchmark -count=1 .PHONY: test_benchmark_automation @@ -204,11 +194,9 @@ build_plugin_docker_image: # args: the args to pass to the test runner, example: args="--focus @cron -p" # product: the product to run tests for, example: product=cron # example usage: make run_test_with_local_image image=chainlink tag=latest-dev product=cron +# remember to put the case CL image name and tag in the TOML config (and don't forget about selected network configuration) .PHONY: run_test_with_local_image run_test_with_local_image: build_docker_image - CHAINLINK_IMAGE=$(image) \ - CHAINLINK_VERSION=$(tag) \ - SELECTED_NETWORKS="SIMULATED,SIMULATED_1,SIMULATED_2" \ ARGS="$(args)" \ PRODUCT=$(product) \ ./scripts/run_product_tests diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index 624df39c479..95b538129c7 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -4,6 +4,7 @@ package actions import ( "crypto/ecdsa" "encoding/json" + "errors" "fmt" "math/big" "strings" @@ -258,10 +259,11 @@ func TeardownSuite( chainlinkNodes []*client.ChainlinkK8sClient, optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics failingLogLevel zapcore.Level, // Examines logs after the test, and fails the test if any Chainlink logs are found at or above provided level + grafnaUrlProvider testreporters.GrafanaURLProvider, clients ...blockchain.EVMClient, ) error { l := logging.GetTestLogger(t) - if err := testreporters.WriteTeardownLogs(t, env, optionalTestReporter, failingLogLevel); err != nil { + if err := testreporters.WriteTeardownLogs(t, env, optionalTestReporter, failingLogLevel, grafnaUrlProvider); err != nil { return fmt.Errorf("Error dumping environment logs, leaving environment running for manual retrieval, err: %w", err) } // Delete all jobs to stop depleting the funds @@ -302,11 +304,12 @@ func TeardownRemoteSuite( namespace string, chainlinkNodes []*client.ChainlinkK8sClient, optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics + grafnaUrlProvider testreporters.GrafanaURLProvider, client blockchain.EVMClient, ) error { l := logging.GetTestLogger(t) var err error - if err = testreporters.SendReport(t, namespace, "./", optionalTestReporter); err != nil { + if err = testreporters.SendReport(t, namespace, "./", optionalTestReporter, grafnaUrlProvider); err != nil { l.Warn().Err(err).Msg("Error writing test report") } // Delete all jobs to stop depleting the funds @@ -415,8 +418,8 @@ func UpgradeChainlinkNodeVersions( newImage, newVersion string, nodes ...*client.ChainlinkK8sClient, ) error { - if newImage == "" && newVersion == "" { - return fmt.Errorf("unable to upgrade node version, found empty image and version, must provide either a new image or a new version") + if newImage == "" || newVersion == "" { + return errors.New("New image and new version is needed to upgrade the node") } for _, node := range nodes { if err := node.UpgradeVersion(testEnvironment, newImage, newVersion); err != nil { diff --git a/integration-tests/actions/actions_local.go b/integration-tests/actions/actions_local.go index d4913cabd8a..8ac623d8841 100644 --- a/integration-tests/actions/actions_local.go +++ b/integration-tests/actions/actions_local.go @@ -2,8 +2,6 @@ package actions import ( - "fmt" - "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" ) @@ -13,9 +11,6 @@ func UpgradeChainlinkNodeVersionsLocal( newImage, newVersion string, nodes ...*test_env.ClNode, ) error { - if newImage == "" && newVersion == "" { - return fmt.Errorf("unable to upgrade node version, found empty image and version, must provide either a new image or a new version") - } for _, node := range nodes { if err := node.UpgradeVersion(newImage, newVersion); err != nil { return err diff --git a/integration-tests/actions/private_network.go b/integration-tests/actions/private_network.go index c7556f8061b..7f8bfe8bb2c 100644 --- a/integration-tests/actions/private_network.go +++ b/integration-tests/actions/private_network.go @@ -1,33 +1,28 @@ package actions import ( - "errors" - "github.com/rs/zerolog" ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) -func EthereumNetworkConfigFromEnvOrDefault(l zerolog.Logger) (network ctf_test_env.EthereumNetwork, err error) { - chainConfig := ctf_test_env.EthereumChainConfig{ - SecondsPerSlot: 8, - SlotsPerEpoch: 4, - } - - ethBuilder := ctf_test_env.NewEthereumNetworkBuilder() - network, err = ethBuilder. - WithExecClientFromEnvVar(). - WithEthereumChainConfig(chainConfig). - Build() - - if errors.Is(err, ctf_test_env.ErrMissingExecClientEnvVar) { - l.Warn().Msg("No exec client env var set, will use old geth") - ethBuilder = ctf_test_env.NewEthereumNetworkBuilder() +func EthereumNetworkConfigFromConfig(l zerolog.Logger, config tc.GlobalTestConfig) (network ctf_test_env.EthereumNetwork, err error) { + if config.GetPrivateEthereumNetworkConfig() == nil { + l.Warn().Msg("No TOML private ethereum network config found, will use old geth") + ethBuilder := ctf_test_env.NewEthereumNetworkBuilder() network, err = ethBuilder. WithConsensusType(ctf_test_env.ConsensusType_PoW). WithExecutionLayer(ctf_test_env.ExecutionLayer_Geth). Build() + + return } + ethBuilder := ctf_test_env.NewEthereumNetworkBuilder() + network, err = ethBuilder. + WithExistingConfig(*config.GetPrivateEthereumNetworkConfig()). + Build() + return } diff --git a/integration-tests/actions/vrfv2_actions/vrfv2_config/config.go b/integration-tests/actions/vrfv2_actions/vrfv2_config/config.go deleted file mode 100644 index 36d266fec2d..00000000000 --- a/integration-tests/actions/vrfv2_actions/vrfv2_config/config.go +++ /dev/null @@ -1,54 +0,0 @@ -package vrfv2_config - -import "time" - -type VRFV2Config struct { - ChainlinkNodeFunding float64 `envconfig:"CHAINLINK_NODE_FUNDING" default:".1"` // Amount of native currency to fund each chainlink node with - CLNodeMaxGasPriceGWei int64 `envconfig:"MAX_GAS_PRICE_GWEI" default:"10"` // Max gas price in GWei for the chainlink node - IsNativePayment bool `envconfig:"IS_NATIVE_PAYMENT" default:"false"` // Whether to use native payment or LINK token - LinkNativeFeedResponse int64 `envconfig:"LINK_NATIVE_FEED_RESPONSE" default:"1000000000000000000"` // Response of the LINK/ETH feed - MinimumConfirmations uint16 `envconfig:"MINIMUM_CONFIRMATIONS" default:"3"` // Minimum number of confirmations for the VRF Coordinator - SubscriptionFundingAmountLink float64 `envconfig:"SUBSCRIPTION_FUNDING_AMOUNT_LINK" default:"5"` // Amount of LINK to fund the subscription with - NumberOfWords uint32 `envconfig:"NUMBER_OF_WORDS" default:"3"` // Number of words to request - CallbackGasLimit uint32 `envconfig:"CALLBACK_GAS_LIMIT" default:"1000000"` // Gas limit for the callback - MaxGasLimitCoordinatorConfig uint32 `envconfig:"MAX_GAS_LIMIT_COORDINATOR_CONFIG" default:"2500000"` // Max gas limit for the VRF Coordinator config - FallbackWeiPerUnitLink int64 `envconfig:"FALLBACK_WEI_PER_UNIT_LINK" default:"60000000000000000"` // Fallback wei per unit LINK for the VRF Coordinator config - StalenessSeconds uint32 `envconfig:"STALENESS_SECONDS" default:"86400"` // Staleness in seconds for the VRF Coordinator config - GasAfterPaymentCalculation uint32 `envconfig:"GAS_AFTER_PAYMENT_CALCULATION" default:"33825"` // Gas after payment calculation for the VRF Coordinator config - FulfillmentFlatFeeLinkPPMTier1 uint32 `envconfig:"FULFILLMENT_FLAT_FEE_LINK_PPM_TIER_1" default:"500"` - FulfillmentFlatFeeLinkPPMTier2 uint32 `envconfig:"FULFILLMENT_FLAT_FEE_LINK_PPM_TIER_2" default:"500"` - FulfillmentFlatFeeLinkPPMTier3 uint32 `envconfig:"FULFILLMENT_FLAT_FEE_LINK_PPM_TIER_3" default:"500"` - FulfillmentFlatFeeLinkPPMTier4 uint32 `envconfig:"FULFILLMENT_FLAT_FEE_LINK_PPM_TIER_4" default:"500"` - FulfillmentFlatFeeLinkPPMTier5 uint32 `envconfig:"FULFILLMENT_FLAT_FEE_LINK_PPM_TIER_5" default:"500"` - ReqsForTier2 int64 `envconfig:"REQS_FOR_TIER_2" default:"0"` - ReqsForTier3 int64 `envconfig:"REQS_FOR_TIER_3" default:"0"` - ReqsForTier4 int64 `envconfig:"REQS_FOR_TIER_4" default:"0"` - ReqsForTier5 int64 `envconfig:"REQS_FOR_TIER_5" default:"0"` - - NumberOfSubToCreate int `envconfig:"NUMBER_OF_SUB_TO_CREATE" default:"1"` // Number of subscriptions to create - - RandomnessRequestCountPerRequest uint16 `envconfig:"RANDOMNESS_REQUEST_COUNT_PER_REQUEST" default:"1"` // How many randomness requests to send per request - RandomnessRequestCountPerRequestDeviation uint16 `envconfig:"RANDOMNESS_REQUEST_COUNT_PER_REQUEST_DEVIATION" default:"0"` // How many randomness requests to send per request - - RandomWordsFulfilledEventTimeout time.Duration `envconfig:"RANDOM_WORDS_FULFILLED_EVENT_TIMEOUT" default:"2m"` // How long to wait for the RandomWordsFulfilled event to be emitted - - //Wrapper Config - WrapperGasOverhead uint32 `envconfig:"WRAPPER_GAS_OVERHEAD" default:"50000"` - CoordinatorGasOverhead uint32 `envconfig:"COORDINATOR_GAS_OVERHEAD" default:"52000"` - WrapperPremiumPercentage uint8 `envconfig:"WRAPPER_PREMIUM_PERCENTAGE" default:"25"` - WrapperMaxNumberOfWords uint8 `envconfig:"WRAPPER_MAX_NUMBER_OF_WORDS" default:"10"` - WrapperConsumerFundingAmountNativeToken float64 `envconfig:"WRAPPER_CONSUMER_FUNDING_AMOUNT_NATIVE_TOKEN" default:"1"` - WrapperConsumerFundingAmountLink int64 `envconfig:"WRAPPER_CONSUMER_FUNDING_AMOUNT_LINK" default:"10"` - - //LOAD/SOAK Test Config - TestDuration time.Duration `envconfig:"TEST_DURATION" default:"3m"` // How long to run the test for - RPS int64 `envconfig:"RPS" default:"1"` // How many requests per second to send - RateLimitUnitDuration time.Duration `envconfig:"RATE_LIMIT_UNIT_DURATION" default:"1m"` - //Using existing environment and contracts - UseExistingEnv bool `envconfig:"USE_EXISTING_ENV" default:"false"` // Whether to use an existing environment or create a new one - CoordinatorAddress string `envconfig:"COORDINATOR_ADDRESS" default:""` // Coordinator address - ConsumerAddress string `envconfig:"CONSUMER_ADDRESS" default:""` // Consumer address - LinkAddress string `envconfig:"LINK_ADDRESS" default:""` // Link address - SubID uint64 `envconfig:"SUB_ID" default:""` // Subscription ID - KeyHash string `envconfig:"KEY_HASH" default:""` -} diff --git a/integration-tests/actions/vrfv2_actions/vrfv2_steps.go b/integration-tests/actions/vrfv2_actions/vrfv2_steps.go index 15148ce9682..1a958548965 100644 --- a/integration-tests/actions/vrfv2_actions/vrfv2_steps.go +++ b/integration-tests/actions/vrfv2_actions/vrfv2_steps.go @@ -12,7 +12,6 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_config" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" @@ -26,6 +25,9 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + "github.com/smartcontractkit/chainlink/integration-tests/types" ) var ( @@ -283,7 +285,7 @@ func FundVRFCoordinatorV2Subscription( // SetupVRFV2Environment will create specified number of subscriptions and add the same conumer/s to each of them func SetupVRFV2Environment( env *test_env.CLClusterTestEnv, - vrfv2Config vrfv2_config.VRFV2Config, + vrfv2TestConfig types.VRFv2TestConfig, useVRFOwner bool, useTestCoordinator bool, linkToken contracts.LinkToken, @@ -307,25 +309,25 @@ func SetupVRFV2Environment( if err != nil { return nil, nil, nil, fmt.Errorf("%s, err %w", ErrDeployVRFV2Contracts, err) } - + vrfv2Config := vrfv2TestConfig.GetVRFv2Config().General vrfCoordinatorV2FeeConfig := vrf_coordinator_v2.VRFCoordinatorV2FeeConfig{ - FulfillmentFlatFeeLinkPPMTier1: vrfv2Config.FulfillmentFlatFeeLinkPPMTier1, - FulfillmentFlatFeeLinkPPMTier2: vrfv2Config.FulfillmentFlatFeeLinkPPMTier2, - FulfillmentFlatFeeLinkPPMTier3: vrfv2Config.FulfillmentFlatFeeLinkPPMTier3, - FulfillmentFlatFeeLinkPPMTier4: vrfv2Config.FulfillmentFlatFeeLinkPPMTier4, - FulfillmentFlatFeeLinkPPMTier5: vrfv2Config.FulfillmentFlatFeeLinkPPMTier5, - ReqsForTier2: big.NewInt(vrfv2Config.ReqsForTier2), - ReqsForTier3: big.NewInt(vrfv2Config.ReqsForTier3), - ReqsForTier4: big.NewInt(vrfv2Config.ReqsForTier4), - ReqsForTier5: big.NewInt(vrfv2Config.ReqsForTier5)} + FulfillmentFlatFeeLinkPPMTier1: *vrfv2Config.FulfillmentFlatFeeLinkPPMTier1, + FulfillmentFlatFeeLinkPPMTier2: *vrfv2Config.FulfillmentFlatFeeLinkPPMTier2, + FulfillmentFlatFeeLinkPPMTier3: *vrfv2Config.FulfillmentFlatFeeLinkPPMTier3, + FulfillmentFlatFeeLinkPPMTier4: *vrfv2Config.FulfillmentFlatFeeLinkPPMTier4, + FulfillmentFlatFeeLinkPPMTier5: *vrfv2Config.FulfillmentFlatFeeLinkPPMTier5, + ReqsForTier2: big.NewInt(*vrfv2Config.ReqsForTier2), + ReqsForTier3: big.NewInt(*vrfv2Config.ReqsForTier3), + ReqsForTier4: big.NewInt(*vrfv2Config.ReqsForTier4), + ReqsForTier5: big.NewInt(*vrfv2Config.ReqsForTier5)} l.Info().Str("Coordinator", vrfv2Contracts.Coordinator.Address()).Msg("Setting Coordinator Config") err = vrfv2Contracts.Coordinator.SetConfig( - vrfv2Config.MinimumConfirmations, - vrfv2Config.MaxGasLimitCoordinatorConfig, - vrfv2Config.StalenessSeconds, - vrfv2Config.GasAfterPaymentCalculation, - big.NewInt(vrfv2Config.FallbackWeiPerUnitLink), + *vrfv2Config.MinimumConfirmations, + *vrfv2Config.MaxGasLimitCoordinatorConfig, + *vrfv2Config.StalenessSeconds, + *vrfv2Config.GasAfterPaymentCalculation, + big.NewInt(*vrfv2Config.FallbackWeiPerUnitLink), vrfCoordinatorV2FeeConfig, ) if err != nil { @@ -341,7 +343,7 @@ func SetupVRFV2Environment( Msg("Creating and funding subscriptions, adding consumers") subIDs, err := CreateFundSubsAndAddConsumers( env, - vrfv2Config, + big.NewFloat(*vrfv2Config.SubscriptionFundingAmountLink), linkToken, vrfv2Contracts.Coordinator, vrfv2Contracts.LoadTestConsumers, numberOfSubToCreate) if err != nil { @@ -365,7 +367,7 @@ func SetupVRFV2Environment( } chainID := env.EVMClient.GetChainID() - newNativeTokenKeyAddresses, err := CreateAndFundSendingKeys(env, vrfv2Config, numberOfTxKeysToCreate, chainID) + newNativeTokenKeyAddresses, err := CreateAndFundSendingKeys(env, vrfv2TestConfig, numberOfTxKeysToCreate, chainID) if err != nil { return nil, nil, nil, err } @@ -402,7 +404,7 @@ func SetupVRFV2Environment( CoordinatorAddress: vrfv2Contracts.Coordinator.Address(), FromAddresses: allNativeTokenKeyAddressStrings, EVMChainID: chainID.String(), - MinIncomingConfirmations: int(vrfv2Config.MinimumConfirmations), + MinIncomingConfirmations: int(*vrfv2Config.MinimumConfirmations), PublicKey: pubKeyCompressed, EstimateGasMultiplier: 1, BatchFulfillmentEnabled: false, @@ -425,7 +427,7 @@ func SetupVRFV2Environment( // [[EVM.KeySpecific]] // Key = '...' nodeConfig := node.NewConfig(env.ClCluster.Nodes[0].NodeConfig, - node.WithVRFv2EVMEstimator(allNativeTokenKeyAddressStrings, vrfv2Config.CLNodeMaxGasPriceGWei), + node.WithVRFv2EVMEstimator(allNativeTokenKeyAddressStrings, *vrfv2Config.CLNodeMaxGasPriceGWei), ) l.Info().Msg("Restarting Node with new sending key PriceMax configuration") err = env.ClCluster.Nodes[0].Restart(nodeConfig) @@ -492,7 +494,7 @@ func setupVRFOwnerContract(env *test_env.CLClusterTestEnv, vrfv2Contracts *VRFV2 func SetupVRFV2WrapperEnvironment( env *test_env.CLClusterTestEnv, - vrfv2Config vrfv2_config.VRFV2Config, + vrfv2TestConfig tc.VRFv2TestConfig, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.MockETHLINKFeed, coordinator contracts.VRFCoordinatorV2, @@ -516,13 +518,15 @@ func SetupVRFV2WrapperEnvironment( return nil, nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err) } + vrfv2Config := vrfv2TestConfig.GetVRFv2Config() + // Configure VRF v2 wrapper contract err = wrapperContracts.VRFV2Wrapper.SetConfig( - vrfv2Config.WrapperGasOverhead, - vrfv2Config.CoordinatorGasOverhead, - vrfv2Config.WrapperPremiumPercentage, + *vrfv2Config.General.WrapperGasOverhead, + *vrfv2Config.General.CoordinatorGasOverhead, + *vrfv2Config.General.WrapperPremiumPercentage, keyHash, - vrfv2Config.WrapperMaxNumberOfWords, + *vrfv2Config.General.WrapperMaxNumberOfWords, ) if err != nil { return nil, nil, err @@ -543,7 +547,7 @@ func SetupVRFV2WrapperEnvironment( } // Fund wrapper subscription - err = FundSubscriptions(env, vrfv2Config.SubscriptionFundingAmountLink, linkToken, coordinator, []uint64{wrapperSubID}) + err = FundSubscriptions(env, big.NewFloat(*vrfv2Config.General.SubscriptionFundingAmountLink), linkToken, coordinator, []uint64{wrapperSubID}) if err != nil { return nil, nil, err } @@ -551,7 +555,7 @@ func SetupVRFV2WrapperEnvironment( // Fund consumer with LINK err = linkToken.Transfer( wrapperContracts.LoadTestConsumers[0].Address(), - big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(vrfv2Config.WrapperConsumerFundingAmountLink)), + big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(*vrfv2Config.General.WrapperConsumerFundingAmountLink)), ) if err != nil { return nil, nil, err @@ -564,7 +568,7 @@ func SetupVRFV2WrapperEnvironment( return wrapperContracts, &wrapperSubID, nil } -func CreateAndFundSendingKeys(env *test_env.CLClusterTestEnv, vrfv2Config vrfv2_config.VRFV2Config, numberOfNativeTokenAddressesToCreate int, chainID *big.Int) ([]string, error) { +func CreateAndFundSendingKeys(env *test_env.CLClusterTestEnv, testConfig tc.CommonTestConfig, numberOfNativeTokenAddressesToCreate int, chainID *big.Int) ([]string, error) { var newNativeTokenKeyAddresses []string for i := 0; i < numberOfNativeTokenAddressesToCreate; i++ { newTxKey, response, err := env.ClCluster.NodeAPIs()[0].CreateTxKey("evm", chainID.String()) @@ -575,7 +579,7 @@ func CreateAndFundSendingKeys(env *test_env.CLClusterTestEnv, vrfv2Config vrfv2_ return nil, fmt.Errorf("error creating transaction key - response code, err %d", response.StatusCode) } newNativeTokenKeyAddresses = append(newNativeTokenKeyAddresses, newTxKey.Data.ID) - err = actions.FundAddress(env.EVMClient, newTxKey.Data.ID, big.NewFloat(vrfv2Config.ChainlinkNodeFunding)) + err = actions.FundAddress(env.EVMClient, newTxKey.Data.ID, big.NewFloat(*testConfig.GetCommonConfig().ChainlinkNodeFunding)) if err != nil { return nil, err } @@ -585,13 +589,13 @@ func CreateAndFundSendingKeys(env *test_env.CLClusterTestEnv, vrfv2Config vrfv2_ func CreateFundSubsAndAddConsumers( env *test_env.CLClusterTestEnv, - vrfv2Config vrfv2_config.VRFV2Config, + subscriptionFundingAmountLink *big.Float, linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV2, consumers []contracts.VRFv2LoadTestConsumer, numberOfSubToCreate int, ) ([]uint64, error) { - subIDs, err := CreateSubsAndFund(env, vrfv2Config, linkToken, coordinator, numberOfSubToCreate) + subIDs, err := CreateSubsAndFund(env, subscriptionFundingAmountLink, linkToken, coordinator, numberOfSubToCreate) if err != nil { return nil, err } @@ -619,7 +623,7 @@ func CreateFundSubsAndAddConsumers( func CreateSubsAndFund( env *test_env.CLClusterTestEnv, - vrfv2Config vrfv2_config.VRFV2Config, + subscriptionFundingAmountLink *big.Float, linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV2, subAmountToCreate int, @@ -632,7 +636,7 @@ func CreateSubsAndFund( if err != nil { return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err) } - err = FundSubscriptions(env, vrfv2Config.SubscriptionFundingAmountLink, linkToken, coordinator, subs) + err = FundSubscriptions(env, subscriptionFundingAmountLink, linkToken, coordinator, subs) if err != nil { return nil, err } @@ -694,14 +698,14 @@ func CreateSubAndFindSubID(env *test_env.CLClusterTestEnv, coordinator contracts func FundSubscriptions( env *test_env.CLClusterTestEnv, - fundingAmountLink float64, + subscriptionFundingAmountLink *big.Float, linkAddress contracts.LinkToken, coordinator contracts.VRFCoordinatorV2, subIDs []uint64, ) error { for _, subID := range subIDs { //Link Billing - amountJuels := conversions.EtherToWei(big.NewFloat(fundingAmountLink)) + amountJuels := conversions.EtherToWei(subscriptionFundingAmountLink) err := FundVRFCoordinatorV2Subscription(linkAddress, coordinator, env.EVMClient, subID, amountJuels) if err != nil { return fmt.Errorf("%s, err %w", ErrFundSubWithLinkToken, err) @@ -715,20 +719,23 @@ func FundSubscriptions( } func DirectFundingRequestRandomnessAndWaitForFulfillment( + l zerolog.Logger, consumer contracts.VRFv2WrapperLoadTestConsumer, coordinator contracts.VRFCoordinatorV2, - vrfv2Data *VRFV2Data, subID uint64, + vrfv2Data *VRFV2Data, + minimumConfirmations uint16, + callbackGasLimit uint32, + numberOfWords uint32, randomnessRequestCountPerRequest uint16, - vrfv2Config vrfv2_config.VRFV2Config, + randomnessRequestCountPerRequestDeviation uint16, randomWordsFulfilledEventTimeout time.Duration, - l zerolog.Logger, ) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, error) { - logRandRequest(consumer.Address(), coordinator.Address(), subID, vrfv2Config, l) + logRandRequest(l, consumer.Address(), coordinator.Address(), subID, minimumConfirmations, callbackGasLimit, numberOfWords, randomnessRequestCountPerRequest, randomnessRequestCountPerRequestDeviation) _, err := consumer.RequestRandomness( - vrfv2Config.MinimumConfirmations, - vrfv2Config.CallbackGasLimit, - vrfv2Config.NumberOfWords, + minimumConfirmations, + callbackGasLimit, + numberOfWords, randomnessRequestCountPerRequest, ) if err != nil { @@ -750,22 +757,25 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment( } func RequestRandomnessAndWaitForFulfillment( + l zerolog.Logger, consumer contracts.VRFv2LoadTestConsumer, coordinator contracts.VRFCoordinatorV2, - vrfv2Data *VRFV2Data, subID uint64, + vrfv2Data *VRFV2Data, + minimumConfirmations uint16, + callbackGasLimit uint32, + numberOfWords uint32, randomnessRequestCountPerRequest uint16, - vrfv2Config vrfv2_config.VRFV2Config, + randomnessRequestCountPerRequestDeviation uint16, randomWordsFulfilledEventTimeout time.Duration, - l zerolog.Logger, ) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, error) { - logRandRequest(consumer.Address(), coordinator.Address(), subID, vrfv2Config, l) + logRandRequest(l, consumer.Address(), coordinator.Address(), subID, minimumConfirmations, callbackGasLimit, numberOfWords, randomnessRequestCountPerRequest, randomnessRequestCountPerRequestDeviation) _, err := consumer.RequestRandomness( vrfv2Data.KeyHash, subID, - vrfv2Config.MinimumConfirmations, - vrfv2Config.CallbackGasLimit, - vrfv2Config.NumberOfWords, + minimumConfirmations, + callbackGasLimit, + numberOfWords, randomnessRequestCountPerRequest, ) if err != nil { @@ -784,23 +794,26 @@ func RequestRandomnessAndWaitForFulfillment( } func RequestRandomnessWithForceFulfillAndWaitForFulfillment( + l zerolog.Logger, consumer contracts.VRFv2LoadTestConsumer, coordinator contracts.VRFCoordinatorV2, vrfOwner contracts.VRFOwner, vrfv2Data *VRFV2Data, + minimumConfirmations uint16, + callbackGasLimit uint32, + numberOfWords uint32, randomnessRequestCountPerRequest uint16, - vrfv2Config vrfv2_config.VRFV2Config, + randomnessRequestCountPerRequestDeviation uint16, subTopUpAmount *big.Int, linkAddress common.Address, randomWordsFulfilledEventTimeout time.Duration, - l zerolog.Logger, ) (*vrf_coordinator_v2.VRFCoordinatorV2ConfigSet, *vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, *vrf_owner.VRFOwnerRandomWordsForced, error) { - logRandRequest(consumer.Address(), coordinator.Address(), 0, vrfv2Config, l) + logRandRequest(l, consumer.Address(), coordinator.Address(), 0, minimumConfirmations, callbackGasLimit, numberOfWords, randomnessRequestCountPerRequest, randomnessRequestCountPerRequestDeviation) _, err := consumer.RequestRandomWordsWithForceFulfill( vrfv2Data.KeyHash, - vrfv2Config.MinimumConfirmations, - vrfv2Config.CallbackGasLimit, - vrfv2Config.NumberOfWords, + minimumConfirmations, + callbackGasLimit, + numberOfWords, randomnessRequestCountPerRequest, subTopUpAmount, linkAddress, @@ -1013,19 +1026,24 @@ func LogRandomWordsForcedEvent( } func logRandRequest( + l zerolog.Logger, consumer string, coordinator string, subID uint64, - vrfv2Config vrfv2_config.VRFV2Config, - l zerolog.Logger, + minimumConfirmations uint16, + callbackGasLimit uint32, + numberOfWords uint32, + randomnessRequestCountPerRequest uint16, + randomnessRequestCountPerRequestDeviation uint16, ) { l.Debug(). Str("Consumer", consumer). Str("Coordinator", coordinator). Uint64("SubID", subID). - Uint16("MinimumConfirmations", vrfv2Config.MinimumConfirmations). - Uint32("CallbackGasLimit", vrfv2Config.CallbackGasLimit). - Uint16("RandomnessRequestCountPerRequest", vrfv2Config.RandomnessRequestCountPerRequest). - Uint16("RandomnessRequestCountPerRequestDeviation", vrfv2Config.RandomnessRequestCountPerRequestDeviation). + Uint16("MinimumConfirmations", minimumConfirmations). + Uint32("CallbackGasLimit", callbackGasLimit). + Uint32("NumberOfWords", numberOfWords). + Uint16("RandomnessRequestCountPerRequest", randomnessRequestCountPerRequest). + Uint16("RandomnessRequestCountPerRequestDeviation", randomnessRequestCountPerRequestDeviation). Msg("Requesting randomness") } diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go b/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go deleted file mode 100644 index 233b35a2383..00000000000 --- a/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go +++ /dev/null @@ -1,54 +0,0 @@ -package vrfv2plus_config - -import "time" - -const ( - BILLING_TYPE_LINK = "LINK" - BILLING_TYPE_NATIVE = "NATIVE" - BILLING_TYPE_LINK_AND_NATIVE = "LINK_AND_NATIVE" -) - -type VRFV2PlusConfig struct { - ChainlinkNodeFunding float64 `envconfig:"CHAINLINK_NODE_FUNDING" default:".1"` // Amount of native currency to fund each chainlink node with - CLNodeMaxGasPriceGWei int64 `envconfig:"MAX_GAS_PRICE_GWEI" default:"10"` // Max gas price in GWei for the chainlink node - SubscriptionBillingType string `envconfig:"SUBSCRIPTION_BILLING_TYPE" default:"LINK_AND_NATIVE"` // Whether to use native payment or LINK token, or both - LinkNativeFeedResponse int64 `envconfig:"LINK_NATIVE_FEED_RESPONSE" default:"1000000000000000000"` // Response of the LINK/ETH feed - MinimumConfirmations uint16 `envconfig:"MINIMUM_CONFIRMATIONS" default:"3"` // Minimum number of confirmations for the VRF Coordinator - SubscriptionFundingAmountLink float64 `envconfig:"SUBSCRIPTION_FUNDING_AMOUNT_LINK" default:"5"` // Amount of LINK to fund the subscription with - SubscriptionFundingAmountNative float64 `envconfig:"SUBSCRIPTION_FUNDING_AMOUNT_NATIVE" default:"1"` // Amount of native currency to fund the subscription with - NumberOfWords uint32 `envconfig:"NUMBER_OF_WORDS" default:"3"` // Number of words to request - CallbackGasLimit uint32 `envconfig:"CALLBACK_GAS_LIMIT" default:"1000000"` // Gas limit for the callback - MaxGasLimitCoordinatorConfig uint32 `envconfig:"MAX_GAS_LIMIT_COORDINATOR_CONFIG" default:"2500000"` // Max gas limit for the VRF Coordinator config - FallbackWeiPerUnitLink int64 `envconfig:"FALLBACK_WEI_PER_UNIT_LINK" default:"60000000000000000"` // Fallback wei per unit LINK for the VRF Coordinator config - StalenessSeconds uint32 `envconfig:"STALENESS_SECONDS" default:"86400"` // Staleness in seconds for the VRF Coordinator config - GasAfterPaymentCalculation uint32 `envconfig:"GAS_AFTER_PAYMENT_CALCULATION" default:"33825"` // Gas after payment calculation for the VRF Coordinator config - FulfillmentFlatFeeLinkPPM uint32 `envconfig:"FULFILLMENT_FLAT_FEE_LINK_PPM" default:"500"` // Flat fee in ppm for LINK for the VRF Coordinator config - FulfillmentFlatFeeNativePPM uint32 `envconfig:"FULFILLMENT_FLAT_FEE_NATIVE_PPM" default:"500"` // Flat fee in ppm for native currency for the VRF Coordinator config - - NumberOfSubToCreate int `envconfig:"NUMBER_OF_SUB_TO_CREATE" default:"1"` // Number of subscriptions to create - - RandomnessRequestCountPerRequest uint16 `envconfig:"RANDOMNESS_REQUEST_COUNT_PER_REQUEST" default:"1"` // How many randomness requests to send per request - RandomnessRequestCountPerRequestDeviation uint16 `envconfig:"RANDOMNESS_REQUEST_COUNT_PER_REQUEST_DEVIATION" default:"0"` // How many randomness requests to send per request - - RandomWordsFulfilledEventTimeout time.Duration `envconfig:"RANDOM_WORDS_FULFILLED_EVENT_TIMEOUT" default:"2m"` // How long to wait for the RandomWordsFulfilled event to be emitted - - //Wrapper Config - WrapperGasOverhead uint32 `envconfig:"WRAPPER_GAS_OVERHEAD" default:"50000"` - CoordinatorGasOverhead uint32 `envconfig:"COORDINATOR_GAS_OVERHEAD" default:"52000"` - WrapperPremiumPercentage uint8 `envconfig:"WRAPPER_PREMIUM_PERCENTAGE" default:"25"` - WrapperMaxNumberOfWords uint8 `envconfig:"WRAPPER_MAX_NUMBER_OF_WORDS" default:"10"` - WrapperConsumerFundingAmountNativeToken float64 `envconfig:"WRAPPER_CONSUMER_FUNDING_AMOUNT_NATIVE_TOKEN" default:"1"` - WrapperConsumerFundingAmountLink int64 `envconfig:"WRAPPER_CONSUMER_FUNDING_AMOUNT_LINK" default:"10"` - - //LOAD/SOAK Test Config - TestDuration time.Duration `envconfig:"TEST_DURATION" default:"3m"` // How long to run the test for - RPS int64 `envconfig:"RPS" default:"1"` // How many requests per second to send - RateLimitUnitDuration time.Duration `envconfig:"RATE_LIMIT_UNIT_DURATION" default:"1m"` - //Using existing environment and contracts - UseExistingEnv bool `envconfig:"USE_EXISTING_ENV" default:"false"` // Whether to use an existing environment or create a new one - CoordinatorAddress string `envconfig:"COORDINATOR_ADDRESS" default:""` // Coordinator address - ConsumerAddress string `envconfig:"CONSUMER_ADDRESS" default:""` // Consumer address - LinkAddress string `envconfig:"LINK_ADDRESS" default:""` // Link address - SubID string `envconfig:"SUB_ID" default:""` // Subscription ID - KeyHash string `envconfig:"KEY_HASH" default:""` -} diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go index b19efd1d677..fc2a47f53ef 100644 --- a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go +++ b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go @@ -18,10 +18,12 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" + "github.com/smartcontractkit/chainlink/integration-tests/types" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" @@ -214,7 +216,7 @@ func FundVRFCoordinatorV2_5Subscription( // SetupVRFV2_5Environment will create specified number of subscriptions and add the same conumer/s to each of them func SetupVRFV2_5Environment( env *test_env.CLClusterTestEnv, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + vrfv2PlusTestConfig types.VRFv2PlusTestConfig, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.MockETHLINKFeed, numberOfTxKeysToCreate int, @@ -230,15 +232,16 @@ func SetupVRFV2_5Environment( } l.Info().Str("Coordinator", vrfv2_5Contracts.Coordinator.Address()).Msg("Setting Coordinator Config") + vrfv2PlusConfig := vrfv2PlusTestConfig.GetVRFv2PlusConfig().General err = vrfv2_5Contracts.Coordinator.SetConfig( - vrfv2PlusConfig.MinimumConfirmations, - vrfv2PlusConfig.MaxGasLimitCoordinatorConfig, - vrfv2PlusConfig.StalenessSeconds, - vrfv2PlusConfig.GasAfterPaymentCalculation, - big.NewInt(vrfv2PlusConfig.FallbackWeiPerUnitLink), + *vrfv2PlusConfig.MinimumConfirmations, + *vrfv2PlusConfig.MaxGasLimitCoordinatorConfig, + *vrfv2PlusConfig.StalenessSeconds, + *vrfv2PlusConfig.GasAfterPaymentCalculation, + big.NewInt(*vrfv2PlusConfig.FallbackWeiPerUnitLink), vrf_coordinator_v2_5.VRFCoordinatorV25FeeConfig{ - FulfillmentFlatFeeLinkPPM: vrfv2PlusConfig.FulfillmentFlatFeeLinkPPM, - FulfillmentFlatFeeNativePPM: vrfv2PlusConfig.FulfillmentFlatFeeNativePPM, + FulfillmentFlatFeeLinkPPM: *vrfv2PlusConfig.FulfillmentFlatFeeLinkPPM, + FulfillmentFlatFeeNativePPM: *vrfv2PlusConfig.FulfillmentFlatFeeNativePPM, }, ) if err != nil { @@ -260,9 +263,12 @@ func SetupVRFV2_5Environment( Msg("Creating and funding subscriptions, adding consumers") subIDs, err := CreateFundSubsAndAddConsumers( env, - vrfv2PlusConfig, + big.NewFloat(*vrfv2PlusConfig.SubscriptionFundingAmountNative), + big.NewFloat(*vrfv2PlusConfig.SubscriptionFundingAmountLink), linkToken, - vrfv2_5Contracts.Coordinator, vrfv2_5Contracts.LoadTestConsumers, numberOfSubToCreate) + vrfv2_5Contracts.Coordinator, vrfv2_5Contracts.LoadTestConsumers, + numberOfSubToCreate, + vrfv2plus_config.BillingType(*vrfv2PlusConfig.SubscriptionBillingType)) if err != nil { return nil, nil, nil, err } @@ -284,7 +290,7 @@ func SetupVRFV2_5Environment( } chainID := env.EVMClient.GetChainID() - newNativeTokenKeyAddresses, err := CreateAndFundSendingKeys(env, vrfv2PlusConfig, numberOfTxKeysToCreate, chainID) + newNativeTokenKeyAddresses, err := CreateAndFundSendingKeys(env, vrfv2PlusTestConfig, numberOfTxKeysToCreate, chainID) if err != nil { return nil, nil, nil, err } @@ -299,7 +305,7 @@ func SetupVRFV2_5Environment( CoordinatorAddress: vrfv2_5Contracts.Coordinator.Address(), FromAddresses: allNativeTokenKeyAddresses, EVMChainID: chainID.String(), - MinIncomingConfirmations: int(vrfv2PlusConfig.MinimumConfirmations), + MinIncomingConfirmations: int(*vrfv2PlusConfig.MinimumConfirmations), PublicKey: pubKeyCompressed, EstimateGasMultiplier: 1, BatchFulfillmentEnabled: false, @@ -322,7 +328,7 @@ func SetupVRFV2_5Environment( // Key = '...' nodeConfig := node.NewConfig(env.ClCluster.Nodes[0].NodeConfig, node.WithLogPollInterval(1*time.Second), - node.WithVRFv2EVMEstimator(allNativeTokenKeyAddresses, vrfv2PlusConfig.CLNodeMaxGasPriceGWei), + node.WithVRFv2EVMEstimator(allNativeTokenKeyAddresses, *vrfv2PlusConfig.CLNodeMaxGasPriceGWei), ) l.Info().Msg("Restarting Node with new sending key PriceMax configuration and log poll period configuration") err = env.ClCluster.Nodes[0].Restart(nodeConfig) @@ -347,7 +353,7 @@ func SetupVRFV2_5Environment( return vrfv2_5Contracts, subIDs, &data, nil } -func CreateAndFundSendingKeys(env *test_env.CLClusterTestEnv, vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, numberOfNativeTokenAddressesToCreate int, chainID *big.Int) ([]string, error) { +func CreateAndFundSendingKeys(env *test_env.CLClusterTestEnv, commonTestConfig tc.CommonTestConfig, numberOfNativeTokenAddressesToCreate int, chainID *big.Int) ([]string, error) { var newNativeTokenKeyAddresses []string for i := 0; i < numberOfNativeTokenAddressesToCreate; i++ { newTxKey, response, err := env.ClCluster.NodeAPIs()[0].CreateTxKey("evm", chainID.String()) @@ -358,7 +364,7 @@ func CreateAndFundSendingKeys(env *test_env.CLClusterTestEnv, vrfv2PlusConfig vr return nil, fmt.Errorf("error creating transaction key - response code, err %d", response.StatusCode) } newNativeTokenKeyAddresses = append(newNativeTokenKeyAddresses, newTxKey.Data.ID) - err = actions.FundAddress(env.EVMClient, newTxKey.Data.ID, big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)) + err = actions.FundAddress(env.EVMClient, newTxKey.Data.ID, big.NewFloat(*commonTestConfig.GetCommonConfig().ChainlinkNodeFunding)) if err != nil { return nil, err } @@ -368,13 +374,23 @@ func CreateAndFundSendingKeys(env *test_env.CLClusterTestEnv, vrfv2PlusConfig vr func CreateFundSubsAndAddConsumers( env *test_env.CLClusterTestEnv, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + subscriptionFundingAmountNative *big.Float, + subscriptionFundingAmountLink *big.Float, linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV2_5, consumers []contracts.VRFv2PlusLoadTestConsumer, numberOfSubToCreate int, + subscriptionBillingType vrfv2plus_config.BillingType, ) ([]*big.Int, error) { - subIDs, err := CreateSubsAndFund(env, vrfv2PlusConfig, linkToken, coordinator, numberOfSubToCreate) + subIDs, err := CreateSubsAndFund( + env, + subscriptionFundingAmountNative, + subscriptionFundingAmountLink, + linkToken, + coordinator, + numberOfSubToCreate, + subscriptionBillingType, + ) if err != nil { return nil, err } @@ -402,10 +418,12 @@ func CreateFundSubsAndAddConsumers( func CreateSubsAndFund( env *test_env.CLClusterTestEnv, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + subscriptionFundingAmountNative *big.Float, + subscriptionFundingAmountLink *big.Float, linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV2_5, subAmountToCreate int, + subscriptionBillingType vrfv2plus_config.BillingType, ) ([]*big.Int, error) { subs, err := CreateSubs(env, coordinator, subAmountToCreate) if err != nil { @@ -415,7 +433,15 @@ func CreateSubsAndFund( if err != nil { return nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err) } - err = FundSubscriptions(env, vrfv2PlusConfig, linkToken, coordinator, subs) + err = FundSubscriptions( + env, + subscriptionFundingAmountNative, + subscriptionFundingAmountLink, + linkToken, + coordinator, + subs, + subscriptionBillingType, + ) if err != nil { return nil, err } @@ -477,16 +503,18 @@ func CreateSubAndFindSubID(env *test_env.CLClusterTestEnv, coordinator contracts func FundSubscriptions( env *test_env.CLClusterTestEnv, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + subscriptionFundingAmountNative *big.Float, + subscriptionFundingAmountLink *big.Float, linkAddress contracts.LinkToken, coordinator contracts.VRFCoordinatorV2_5, subIDs []*big.Int, + subscriptionBillingType vrfv2plus_config.BillingType, ) error { for _, subID := range subIDs { - switch vrfv2PlusConfig.SubscriptionBillingType { - case vrfv2plus_config.BILLING_TYPE_NATIVE: + switch subscriptionBillingType { + case vrfv2plus_config.BillingType_Native: //Native Billing - amountWei := conversions.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountNative)) + amountWei := conversions.EtherToWei(subscriptionFundingAmountNative) err := coordinator.FundSubscriptionWithNative( subID, amountWei, @@ -494,16 +522,16 @@ func FundSubscriptions( if err != nil { return fmt.Errorf("%s, err %w", ErrFundSubWithNativeToken, err) } - case vrfv2plus_config.BILLING_TYPE_LINK: + case vrfv2plus_config.BillingType_Link: //Link Billing - amountJuels := conversions.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountLink)) + amountJuels := conversions.EtherToWei(subscriptionFundingAmountLink) err := FundVRFCoordinatorV2_5Subscription(linkAddress, coordinator, env.EVMClient, subID, amountJuels) if err != nil { return fmt.Errorf("%s, err %w", ErrFundSubWithLinkToken, err) } - case vrfv2plus_config.BILLING_TYPE_LINK_AND_NATIVE: + case vrfv2plus_config.BillingType_Link_and_Native: //Native Billing - amountWei := conversions.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountNative)) + amountWei := conversions.EtherToWei(subscriptionFundingAmountNative) err := coordinator.FundSubscriptionWithNative( subID, amountWei, @@ -512,13 +540,13 @@ func FundSubscriptions( return fmt.Errorf("%s, err %w", ErrFundSubWithNativeToken, err) } //Link Billing - amountJuels := conversions.EtherToWei(big.NewFloat(vrfv2PlusConfig.SubscriptionFundingAmountLink)) + amountJuels := conversions.EtherToWei(subscriptionFundingAmountLink) err = FundVRFCoordinatorV2_5Subscription(linkAddress, coordinator, env.EVMClient, subID, amountJuels) if err != nil { return fmt.Errorf("%s, err %w", ErrFundSubWithLinkToken, err) } default: - return fmt.Errorf("invalid billing type: %s", vrfv2PlusConfig.SubscriptionBillingType) + return fmt.Errorf("invalid billing type: %s", subscriptionBillingType) } } err := env.EVMClient.WaitForEvents() @@ -558,19 +586,22 @@ func RequestRandomnessAndWaitForFulfillment( vrfv2PlusData *VRFV2PlusData, subID *big.Int, isNativeBilling bool, + minimumConfirmations uint16, + callbackGasLimit uint32, + numberOfWords uint32, randomnessRequestCountPerRequest uint16, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + randomnessRequestCountPerRequestDeviation uint16, randomWordsFulfilledEventTimeout time.Duration, l zerolog.Logger, ) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) { - logRandRequest(consumer.Address(), coordinator.Address(), subID, isNativeBilling, vrfv2PlusConfig, l) + logRandRequest(l, consumer.Address(), coordinator.Address(), subID, isNativeBilling, minimumConfirmations, callbackGasLimit, numberOfWords, randomnessRequestCountPerRequest, randomnessRequestCountPerRequestDeviation) _, err := consumer.RequestRandomness( vrfv2PlusData.KeyHash, subID, - vrfv2PlusConfig.MinimumConfirmations, - vrfv2PlusConfig.CallbackGasLimit, + minimumConfirmations, + callbackGasLimit, isNativeBilling, - vrfv2PlusConfig.NumberOfWords, + numberOfWords, randomnessRequestCountPerRequest, ) if err != nil { @@ -594,18 +625,22 @@ func RequestRandomnessAndWaitForFulfillmentUpgraded( vrfv2PlusData *VRFV2PlusData, subID *big.Int, isNativeBilling bool, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + minimumConfirmations uint16, + callbackGasLimit uint32, + numberOfWords uint32, + randomnessRequestCountPerRequest uint16, + randomnessRequestCountPerRequestDeviation uint16, l zerolog.Logger, ) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, error) { - logRandRequest(consumer.Address(), coordinator.Address(), subID, isNativeBilling, vrfv2PlusConfig, l) + logRandRequest(l, consumer.Address(), coordinator.Address(), subID, isNativeBilling, minimumConfirmations, callbackGasLimit, numberOfWords, randomnessRequestCountPerRequest, randomnessRequestCountPerRequestDeviation) _, err := consumer.RequestRandomness( vrfv2PlusData.KeyHash, subID, - vrfv2PlusConfig.MinimumConfirmations, - vrfv2PlusConfig.CallbackGasLimit, + minimumConfirmations, + callbackGasLimit, isNativeBilling, - vrfv2PlusConfig.NumberOfWords, - vrfv2PlusConfig.RandomnessRequestCountPerRequest, + numberOfWords, + randomnessRequestCountPerRequest, ) if err != nil { return nil, fmt.Errorf("%s, err %w", ErrRequestRandomness, err) @@ -638,14 +673,14 @@ func RequestRandomnessAndWaitForFulfillmentUpgraded( func SetupVRFV2PlusWrapperEnvironment( env *test_env.CLClusterTestEnv, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + vrfv2PlusTestConfig types.VRFv2PlusTestConfig, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.MockETHLINKFeed, coordinator contracts.VRFCoordinatorV2_5, keyHash [32]byte, wrapperConsumerContractsAmount int, ) (*VRFV2PlusWrapperContracts, *big.Int, error) { - + vrfv2PlusConfig := vrfv2PlusTestConfig.GetVRFv2PlusConfig().General wrapperContracts, err := DeployVRFV2PlusDirectFundingContracts( env.ContractDeployer, env.EVMClient, @@ -664,15 +699,15 @@ func SetupVRFV2PlusWrapperEnvironment( return nil, nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err) } err = wrapperContracts.VRFV2PlusWrapper.SetConfig( - vrfv2PlusConfig.WrapperGasOverhead, - vrfv2PlusConfig.CoordinatorGasOverhead, - vrfv2PlusConfig.WrapperPremiumPercentage, + *vrfv2PlusConfig.WrapperGasOverhead, + *vrfv2PlusConfig.CoordinatorGasOverhead, + *vrfv2PlusConfig.WrapperPremiumPercentage, keyHash, - vrfv2PlusConfig.WrapperMaxNumberOfWords, - vrfv2PlusConfig.StalenessSeconds, - big.NewInt(vrfv2PlusConfig.FallbackWeiPerUnitLink), - vrfv2PlusConfig.FulfillmentFlatFeeLinkPPM, - vrfv2PlusConfig.FulfillmentFlatFeeNativePPM, + *vrfv2PlusConfig.WrapperMaxNumberOfWords, + *vrfv2PlusConfig.StalenessSeconds, + big.NewInt(*vrfv2PlusConfig.FallbackWeiPerUnitLink), + *vrfv2PlusConfig.FulfillmentFlatFeeLinkPPM, + *vrfv2PlusConfig.FulfillmentFlatFeeNativePPM, ) if err != nil { return nil, nil, err @@ -694,7 +729,7 @@ func SetupVRFV2PlusWrapperEnvironment( return nil, nil, fmt.Errorf("%s, err %w", ErrWaitTXsComplete, err) } - err = FundSubscriptions(env, vrfv2PlusConfig, linkToken, coordinator, []*big.Int{wrapperSubID}) + err = FundSubscriptions(env, big.NewFloat(*vrfv2PlusTestConfig.GetVRFv2PlusConfig().General.SubscriptionFundingAmountNative), big.NewFloat(*vrfv2PlusTestConfig.GetVRFv2PlusConfig().General.SubscriptionFundingAmountLink), linkToken, coordinator, []*big.Int{wrapperSubID}, vrfv2plus_config.BillingType(*vrfv2PlusTestConfig.GetVRFv2PlusConfig().General.SubscriptionBillingType)) if err != nil { return nil, nil, err } @@ -702,7 +737,7 @@ func SetupVRFV2PlusWrapperEnvironment( //fund consumer with Link err = linkToken.Transfer( wrapperContracts.LoadTestConsumers[0].Address(), - big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(vrfv2PlusConfig.WrapperConsumerFundingAmountLink)), + big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(*vrfv2PlusConfig.WrapperConsumerFundingAmountLink)), ) if err != nil { return nil, nil, err @@ -713,7 +748,7 @@ func SetupVRFV2PlusWrapperEnvironment( } //fund consumer with Eth - err = wrapperContracts.LoadTestConsumers[0].Fund(big.NewFloat(vrfv2PlusConfig.WrapperConsumerFundingAmountNativeToken)) + err = wrapperContracts.LoadTestConsumers[0].Fund(big.NewFloat(*vrfv2PlusConfig.WrapperConsumerFundingAmountNativeToken)) if err != nil { return nil, nil, err } @@ -771,27 +806,31 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment( vrfv2PlusData *VRFV2PlusData, subID *big.Int, isNativeBilling bool, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + minimumConfirmations uint16, + callbackGasLimit uint32, + numberOfWords uint32, + randomnessRequestCountPerRequest uint16, + randomnessRequestCountPerRequestDeviation uint16, randomWordsFulfilledEventTimeout time.Duration, l zerolog.Logger, ) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) { - logRandRequest(consumer.Address(), coordinator.Address(), subID, isNativeBilling, vrfv2PlusConfig, l) + logRandRequest(l, consumer.Address(), coordinator.Address(), subID, isNativeBilling, minimumConfirmations, callbackGasLimit, numberOfWords, randomnessRequestCountPerRequest, randomnessRequestCountPerRequestDeviation) if isNativeBilling { _, err := consumer.RequestRandomnessNative( - vrfv2PlusConfig.MinimumConfirmations, - vrfv2PlusConfig.CallbackGasLimit, - vrfv2PlusConfig.NumberOfWords, - vrfv2PlusConfig.RandomnessRequestCountPerRequest, + minimumConfirmations, + callbackGasLimit, + numberOfWords, + randomnessRequestCountPerRequest, ) if err != nil { return nil, fmt.Errorf("%s, err %w", ErrRequestRandomnessDirectFundingNativePayment, err) } } else { _, err := consumer.RequestRandomness( - vrfv2PlusConfig.MinimumConfirmations, - vrfv2PlusConfig.CallbackGasLimit, - vrfv2PlusConfig.NumberOfWords, - vrfv2PlusConfig.RandomnessRequestCountPerRequest, + minimumConfirmations, + callbackGasLimit, + numberOfWords, + randomnessRequestCountPerRequest, ) if err != nil { return nil, fmt.Errorf("%s, err %w", ErrRequestRandomnessDirectFundingLinkPayment, err) @@ -1065,20 +1104,25 @@ func LogFulfillmentDetailsNativeBilling( } func logRandRequest( + l zerolog.Logger, consumer string, coordinator string, subID *big.Int, isNativeBilling bool, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, - l zerolog.Logger) { + minimumConfirmations uint16, + callbackGasLimit uint32, + numberOfWords uint32, + randomnessRequestCountPerRequest uint16, + randomnessRequestCountPerRequestDeviation uint16) { l.Debug(). Str("Consumer", consumer). Str("Coordinator", coordinator). Str("SubID", subID.String()). Bool("IsNativePayment", isNativeBilling). - Uint16("MinimumConfirmations", vrfv2PlusConfig.MinimumConfirmations). - Uint32("CallbackGasLimit", vrfv2PlusConfig.CallbackGasLimit). - Uint16("RandomnessRequestCountPerRequest", vrfv2PlusConfig.RandomnessRequestCountPerRequest). - Uint16("RandomnessRequestCountPerRequestDeviation", vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation). + Uint16("MinimumConfirmations", minimumConfirmations). + Uint32("CallbackGasLimit", callbackGasLimit). + Uint32("NumberOfWords", numberOfWords). + Uint16("RandomnessRequestCountPerRequest", randomnessRequestCountPerRequest). + Uint16("RandomnessRequestCountPerRequestDeviation", randomnessRequestCountPerRequestDeviation). Msg("Requesting randomness") } diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go index 015dff1126c..12a7e4c75aa 100644 --- a/integration-tests/benchmark/keeper_test.go +++ b/integration-tests/benchmark/keeper_test.go @@ -3,8 +3,6 @@ package benchmark import ( "fmt" "math/big" - "os" - "strconv" "strings" "testing" "time" @@ -12,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" env_client "github.com/smartcontractkit/chainlink-testing-framework/k8s/client" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/cdk8s/blockscout" @@ -25,6 +24,9 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" + "github.com/smartcontractkit/chainlink/integration-tests/types" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) var ( @@ -111,27 +113,6 @@ LimitDefault = 5_000_000` } ) -var ( - NumberOfNodes, _ = strconv.Atoi(getEnv("NUMBEROFNODES", "6")) - RegistryToTest = getEnv("REGISTRY", "2_1") - NumberOfUpkeeps, _ = strconv.Atoi(getEnv("NUMBEROFUPKEEPS", "500")) - CheckGasToBurn, _ = strconv.ParseInt(getEnv("CHECKGASTOBURN", "100000"), 0, 64) - PerformGasToBurn, _ = strconv.ParseInt(getEnv("PERFORMGASTOBURN", "50000"), 0, 64) - BlockRange, _ = strconv.ParseInt(getEnv("BLOCKRANGE", "3600"), 0, 64) - BlockInterval, _ = strconv.ParseInt(getEnv("BLOCKINTERVAL", "20"), 0, 64) - ChainlinkNodeFunding, _ = strconv.ParseFloat(getEnv("CHAINLINKNODEFUNDING", "0.5"), 64) - MaxPerformGas, _ = strconv.ParseInt(getEnv("MAXPERFORMGAS", "5000000"), 0, 32) - UpkeepGasLimit, _ = strconv.ParseInt(getEnv("UPKEEPGASLIMIT", fmt.Sprint(PerformGasToBurn+100000)), 0, 64) - NumberOfRegistries, _ = strconv.Atoi(getEnv("NUMBEROFREGISTRIES", "1")) - ForceSingleTxnKey, _ = strconv.ParseBool(getEnv("FORCESINGLETXNKEY", "false")) - DeleteJobsOnEnd, _ = strconv.ParseBool(getEnv("DELETEJOBSONEND", "true")) - RegistryAddress = getEnv("REGISTRYADDRESS", "") - RegistrarAddress = getEnv("REGISTRARADDRESS", "") - LinkTokenAddress = getEnv("LINKTOKENADDRESS", "") - EthFeedAddress = getEnv("ETHFEEDADDRESS", "") - GasFeedAddress = getEnv("GASFEEDADDRESS", "") -) - type NetworkConfig struct { upkeepSLA int64 blockTime time.Duration @@ -141,20 +122,26 @@ type NetworkConfig struct { func TestAutomationBenchmark(t *testing.T) { l := logging.GetTestLogger(t) - testEnvironment, benchmarkNetwork := SetupAutomationBenchmarkEnv(t) + testType, err := tc.GetConfigurationNameFromEnv() + require.NoError(t, err, "Error getting test type") + + config, err := tc.GetConfig(testType, tc.Keeper) + require.NoError(t, err, "Error getting test config") + + testEnvironment, benchmarkNetwork := SetupAutomationBenchmarkEnv(t, &config) if testEnvironment.WillUseRemoteRunner() { return } networkName := strings.ReplaceAll(benchmarkNetwork.Name, " ", "") - testName := fmt.Sprintf("%s%s", networkName, RegistryToTest) - l.Info().Str("Test Name", testName).Str("Test Inputs", os.Getenv("TEST_INPUTS")).Msg("Running Benchmark Test") - benchmarkTestNetwork := networkConfig[networkName] + testName := fmt.Sprintf("%s%s", networkName, *config.Keeper.Common.RegistryToTest) + l.Info().Str("Test Name", testName).Msg("Running Benchmark Test") + benchmarkTestNetwork := getNetworkConfig(networkName, &config) l.Info().Str("Namespace", testEnvironment.Cfg.Namespace).Msg("Connected to Keepers Benchmark Environment") chainClient, err := blockchain.NewEVMClient(benchmarkNetwork, testEnvironment, l) require.NoError(t, err, "Error connecting to blockchain") - registryVersions := addRegistry(RegistryToTest) + registryVersions := addRegistry(&config) keeperBenchmarkTest := testsetups.NewKeeperBenchmarkTest(t, testsetups.KeeperBenchmarkTestInputs{ BlockchainClient: chainClient, @@ -166,7 +153,7 @@ func TestAutomationBenchmark(t *testing.T) { CheckGasLimit: uint32(45_000_000), //45M StalenessSeconds: big.NewInt(90_000), GasCeilingMultiplier: uint16(2), - MaxPerformGas: uint32(MaxPerformGas), + MaxPerformGas: uint32(*config.Keeper.Common.MaxPerformGas), MinUpkeepSpend: big.NewInt(0), FallbackGasPrice: big.NewInt(2e11), FallbackLinkPrice: big.NewInt(2e18), @@ -174,27 +161,27 @@ func TestAutomationBenchmark(t *testing.T) { MaxPerformDataSize: uint32(5_000), }, Upkeeps: &testsetups.UpkeepConfig{ - NumberOfUpkeeps: NumberOfUpkeeps, - CheckGasToBurn: CheckGasToBurn, - PerformGasToBurn: PerformGasToBurn, - BlockRange: BlockRange, - BlockInterval: BlockInterval, - UpkeepGasLimit: UpkeepGasLimit, + NumberOfUpkeeps: *config.Keeper.Common.NumberOfUpkeeps, + CheckGasToBurn: *config.Keeper.Common.CheckGasToBurn, + PerformGasToBurn: *config.Keeper.Common.PerformGasToBurn, + BlockRange: *config.Keeper.Common.BlockRange, + BlockInterval: *config.Keeper.Common.BlockInterval, + UpkeepGasLimit: *config.Keeper.Common.UpkeepGasLimit, FirstEligibleBuffer: 1, }, Contracts: &testsetups.PreDeployedContracts{ - RegistrarAddress: RegistrarAddress, - RegistryAddress: RegistryAddress, - LinkTokenAddress: LinkTokenAddress, - EthFeedAddress: EthFeedAddress, - GasFeedAddress: GasFeedAddress, + RegistrarAddress: *config.Keeper.Common.RegistrarAddress, + RegistryAddress: *config.Keeper.Common.RegistryAddress, + LinkTokenAddress: *config.Keeper.Common.LinkTokenAddress, + EthFeedAddress: *config.Keeper.Common.EthFeedAddress, + GasFeedAddress: *config.Keeper.Common.GasFeedAddress, }, ChainlinkNodeFunding: benchmarkTestNetwork.funding, UpkeepSLA: benchmarkTestNetwork.upkeepSLA, BlockTime: benchmarkTestNetwork.blockTime, DeltaStage: benchmarkTestNetwork.deltaStage, - ForceSingleTxnKey: ForceSingleTxnKey, - DeleteJobsOnEnd: DeleteJobsOnEnd, + ForceSingleTxnKey: *config.Keeper.Common.ForceSingleTxKey, + DeleteJobsOnEnd: *config.Keeper.Common.DeleteJobsOnEnd, }, ) t.Cleanup(func() { @@ -202,12 +189,12 @@ func TestAutomationBenchmark(t *testing.T) { l.Error().Err(err).Msg("Error when tearing down remote suite") } }) - keeperBenchmarkTest.Setup(testEnvironment) + keeperBenchmarkTest.Setup(testEnvironment, &config) keeperBenchmarkTest.Run() } -func addRegistry(registryToTest string) []eth_contracts.KeeperRegistryVersion { - switch registryToTest { +func addRegistry(config *tc.TestConfig) []eth_contracts.KeeperRegistryVersion { + switch *config.Keeper.Common.RegistryToTest { case "1_1": return []eth_contracts.KeeperRegistryVersion{eth_contracts.RegistryVersion_1_1} case "1_2": @@ -224,9 +211,9 @@ func addRegistry(registryToTest string) []eth_contracts.KeeperRegistryVersion { return []eth_contracts.KeeperRegistryVersion{eth_contracts.RegistryVersion_2_1, eth_contracts.RegistryVersion_2_0, eth_contracts.RegistryVersion_1_3} case "2_0-Multiple": - return repeatRegistries(eth_contracts.RegistryVersion_2_0, NumberOfRegistries) + return repeatRegistries(eth_contracts.RegistryVersion_2_0, *config.Keeper.Common.NumberOfRegistries) case "2_1-Multiple": - return repeatRegistries(eth_contracts.RegistryVersion_2_1, NumberOfRegistries) + return repeatRegistries(eth_contracts.RegistryVersion_2_1, *config.Keeper.Common.NumberOfRegistries) default: return []eth_contracts.KeeperRegistryVersion{eth_contracts.RegistryVersion_2_0} } @@ -240,6 +227,22 @@ func repeatRegistries(registryVersion eth_contracts.KeeperRegistryVersion, numbe return repeatedRegistries } +func getNetworkConfig(networkName string, config *tc.TestConfig) NetworkConfig { + var nc NetworkConfig + var ok bool + if nc, ok = networkConfig[networkName]; !ok { + return NetworkConfig{} + } + + if networkName == "SimulatedGeth" || networkName == "geth" { + return nc + } + + nc.funding = big.NewFloat(*config.Common.ChainlinkNodeFunding) + + return nc +} + var networkConfig = map[string]NetworkConfig{ "SimulatedGeth": { upkeepSLA: int64(120), //2 minutes @@ -257,99 +260,71 @@ var networkConfig = map[string]NetworkConfig{ upkeepSLA: int64(4), blockTime: 12 * time.Second, deltaStage: time.Duration(0), - funding: big.NewFloat(ChainlinkNodeFunding), }, "ArbitrumGoerli": { upkeepSLA: int64(20), blockTime: time.Second, deltaStage: time.Duration(0), - funding: big.NewFloat(ChainlinkNodeFunding), }, "OptimismGoerli": { upkeepSLA: int64(20), blockTime: time.Second, deltaStage: time.Duration(0), - funding: big.NewFloat(ChainlinkNodeFunding), }, "SepoliaTestnet": { upkeepSLA: int64(4), blockTime: 12 * time.Second, deltaStage: time.Duration(0), - funding: big.NewFloat(ChainlinkNodeFunding), }, "PolygonMumbai": { upkeepSLA: int64(4), blockTime: 12 * time.Second, deltaStage: time.Duration(0), - funding: big.NewFloat(ChainlinkNodeFunding), }, "BaseGoerli": { upkeepSLA: int64(60), blockTime: 2 * time.Second, deltaStage: 20 * time.Second, - funding: big.NewFloat(ChainlinkNodeFunding), }, "ArbitrumSepolia": { upkeepSLA: int64(120), blockTime: time.Second, deltaStage: 20 * time.Second, - funding: big.NewFloat(ChainlinkNodeFunding), }, "LineaGoerli": { upkeepSLA: int64(120), blockTime: time.Second, deltaStage: 20 * time.Second, - funding: big.NewFloat(ChainlinkNodeFunding), }, } -func getEnv(key, fallback string) string { - if inputs, ok := os.LookupEnv("TEST_INPUTS"); ok { - values := strings.Split(inputs, ",") - for _, value := range values { - if strings.Contains(value, key) { - return strings.Split(value, "=")[1] - } - } - } - return fallback -} - -func SetupAutomationBenchmarkEnv(t *testing.T) (*environment.Environment, blockchain.EVMNetwork) { +func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.KeeperBenchmarkTestConfig) (*environment.Environment, blockchain.EVMNetwork) { l := logging.GetTestLogger(t) - testNetwork := networks.MustGetSelectedNetworksFromEnv()[0] // Environment currently being used to run benchmark test on + testNetwork := networks.MustGetSelectedNetworkConfig(keeperTestConfig.GetNetworkConfig())[0] // Environment currently being used to run benchmark test on blockTime := "1" networkDetailTOML := `MinIncomingConfirmations = 1` - if strings.Contains(RegistryToTest, "2_") { - NumberOfNodes++ + numberOfNodes := *keeperTestConfig.GetKeeperConfig().Common.NumberOfNodes + + if strings.Contains(*keeperTestConfig.GetKeeperConfig().Common.RegistryToTest, "2_") { + numberOfNodes++ } - testType := strings.ToLower(getEnv("TEST_TYPE", "benchmark")) testEnvironment := environment.New(&environment.Config{ TTL: time.Hour * 720, // 30 days, NamespacePrefix: fmt.Sprintf( "automation-%s-%s-%s", - testType, + strings.ToLower(keeperTestConfig.GetConfigurationName()), strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-"), - strings.ReplaceAll(strings.ToLower(RegistryToTest), "_", "-"), + strings.ReplaceAll(strings.ToLower(*keeperTestConfig.GetKeeperConfig().Common.RegistryToTest), "_", "-"), ), Test: t, PreventPodEviction: true, }) - // propagate TEST_INPUTS to remote runner - if testEnvironment.WillUseRemoteRunner() { - key := "TEST_INPUTS" - err := os.Setenv(fmt.Sprintf("TEST_%s", key), os.Getenv(key)) - require.NoError(t, err, "failed to set the environment variable TEST_INPUTS for remote runner") - key = "GRAFANA_DASHBOARD_URL" - err = os.Setenv(fmt.Sprintf("TEST_%s", key), getEnv(key, "")) - require.NoError(t, err, "failed to set the environment variable GRAFANA_DASHBOARD_URL for remote runner") - } dbResources := performanceDbResources chainlinkResources := performanceChainlinkResources - if testType == "soak" { + if strings.ToLower(keeperTestConfig.GetConfigurationName()) == "soak" { chainlinkResources = soakChainlinkResources dbResources = soakDbResources } @@ -363,7 +338,7 @@ func SetupAutomationBenchmarkEnv(t *testing.T) (*environment.Environment, blockc Values: map[string]interface{}{ "geth": map[string]interface{}{ "tx": map[string]interface{}{ - "replicas": NumberOfNodes, + "replicas": numberOfNodes, }, "miner": map[string]interface{}{ "replicas": 2, @@ -413,7 +388,7 @@ func SetupAutomationBenchmarkEnv(t *testing.T) (*environment.Environment, blockc // separate RPC urls per CL node internalWsURLs := make([]string, 0) internalHttpURLs := make([]string, 0) - for i := 0; i < NumberOfNodes; i++ { + for i := 0; i < numberOfNodes; i++ { // for simulated-nod-dev each CL node gets its own RPC node if testNetwork.Name == networks.SimulatedEVMNonDev.Name { podName := fmt.Sprintf("%s-ethereum-geth:%d", testNetwork.Name, i) @@ -435,14 +410,22 @@ func SetupAutomationBenchmarkEnv(t *testing.T) (*environment.Environment, blockc } l.Debug().Strs("internalWsURLs", internalWsURLs).Strs("internalHttpURLs", internalHttpURLs).Msg("internalURLs") - for i := 0; i < NumberOfNodes; i++ { + for i := 0; i < numberOfNodes; i++ { testNetwork.HTTPURLs = []string{internalHttpURLs[i]} testNetwork.URLs = []string{internalWsURLs[i]} - testEnvironment.AddHelm(chainlink.New(i, map[string]any{ - "toml": networks.AddNetworkDetailedConfig(keeperBenchmarkBaseTOML, networkDetailTOML, testNetwork), + + var overrideFn = func(_ interface{}, target interface{}) { + ctf_config.MustConfigOverrideChainlinkVersion(keeperTestConfig.GetChainlinkImageConfig(), target) + ctf_config.MightConfigOverridePyroscopeKey(keeperTestConfig.GetPyroscopeConfig(), target) + } + + cd := chainlink.NewWithOverride(i, map[string]any{ + "toml": networks.AddNetworkDetailedConfig(keeperBenchmarkBaseTOML, keeperTestConfig.GetPyroscopeConfig(), networkDetailTOML, testNetwork), "chainlink": chainlinkResources, "db": dbResources, - })) + }, keeperTestConfig.GetChainlinkImageConfig(), overrideFn) + + testEnvironment.AddHelm(cd) } err = testEnvironment.Run() require.NoError(t, err, "Error launching test environment") diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index 06352a93d72..711a3557307 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -11,6 +11,7 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/cdk8s/blockscout" @@ -25,6 +26,8 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) var ( @@ -41,7 +44,7 @@ ListenAddresses = ["0.0.0.0:6690"]` defaultAutomationSettings = map[string]interface{}{ "replicas": 6, - "toml": networks.AddNetworksConfig(baseTOML, networks.MustGetSelectedNetworksFromEnv()[0]), + "toml": "", "db": map[string]interface{}{ "stateful": true, "capacity": "1Gi", @@ -58,11 +61,7 @@ ListenAddresses = ["0.0.0.0:6690"]` }, } - defaultEthereumSettings = ðereum.Props{ - // utils.MustGetSelectedNetworksFromEnv() - NetworkName: networks.MustGetSelectedNetworksFromEnv()[0].Name, - Simulated: networks.MustGetSelectedNetworksFromEnv()[0].Simulated, - WsURLs: networks.MustGetSelectedNetworksFromEnv()[0].URLs, + defaultEthereumSettings = ethereum.Props{ Values: map[string]interface{}{ "resources": map[string]interface{}{ "requests": map[string]interface{}{ @@ -96,6 +95,20 @@ ListenAddresses = ["0.0.0.0:6690"]` } ) +func getDefaultAutomationSettings(config *tc.TestConfig) map[string]interface{} { + defaultAutomationSettings["toml"] = networks.AddNetworksConfig(baseTOML, config.Pyroscope, networks.MustGetSelectedNetworkConfig(config.Network)[0]) + return defaultAutomationSettings +} + +func getDefaultEthereumSettings(config *tc.TestConfig) *ethereum.Props { + network := networks.MustGetSelectedNetworkConfig(config.Network)[0] + defaultEthereumSettings.NetworkName = network.Name + defaultEthereumSettings.Simulated = network.Simulated + defaultEthereumSettings.WsURLs = network.URLs + + return &defaultEthereumSettings +} + type KeeperConsumerContracts int32 const ( @@ -120,6 +133,18 @@ func TestAutomationChaos(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() + config, err := tc.GetConfig("Chaos", tc.Automation) + if err != nil { + t.Fatal(err) + } + + var overrideFn = func(_ interface{}, target interface{}) { + ctf_config.MustConfigOverrideChainlinkVersion(config.ChainlinkImage, target) + ctf_config.MightConfigOverridePyroscopeKey(config.Pyroscope, target) + } + + chainlinkCfg := chainlink.NewWithOverride(0, getDefaultAutomationSettings(&config), config.ChainlinkImage, overrideFn) + testCases := map[string]struct { networkChart environment.ConnectedChart clChart environment.ConnectedChart @@ -128,8 +153,8 @@ func TestAutomationChaos(t *testing.T) { }{ // see ocr_chaos.test.go for comments PodChaosFailMinorityNodes: { - ethereum.New(defaultEthereumSettings), - chainlink.New(0, defaultAutomationSettings), + ethereum.New(getDefaultEthereumSettings(&config)), + chainlinkCfg, chaos.NewFailPods, &chaos.Props{ LabelsSelector: &map[string]*string{ChaosGroupMinority: ptr.Ptr("1")}, @@ -137,8 +162,8 @@ func TestAutomationChaos(t *testing.T) { }, }, PodChaosFailMajorityNodes: { - ethereum.New(defaultEthereumSettings), - chainlink.New(0, defaultAutomationSettings), + ethereum.New(getDefaultEthereumSettings(&config)), + chainlinkCfg, chaos.NewFailPods, &chaos.Props{ LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")}, @@ -146,8 +171,8 @@ func TestAutomationChaos(t *testing.T) { }, }, PodChaosFailMajorityDB: { - ethereum.New(defaultEthereumSettings), - chainlink.New(0, defaultAutomationSettings), + ethereum.New(getDefaultEthereumSettings(&config)), + chainlinkCfg, chaos.NewFailPods, &chaos.Props{ LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")}, @@ -156,8 +181,8 @@ func TestAutomationChaos(t *testing.T) { }, }, NetworkChaosFailMajorityNetwork: { - ethereum.New(defaultEthereumSettings), - chainlink.New(0, defaultAutomationSettings), + ethereum.New(getDefaultEthereumSettings(&config)), + chainlinkCfg, chaos.NewNetworkPartition, &chaos.Props{ FromLabels: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")}, @@ -166,8 +191,8 @@ func TestAutomationChaos(t *testing.T) { }, }, NetworkChaosFailBlockchainNode: { - ethereum.New(defaultEthereumSettings), - chainlink.New(0, defaultAutomationSettings), + ethereum.New(getDefaultEthereumSettings(&config)), + chainlinkCfg, chaos.NewNetworkPartition, &chaos.Props{ FromLabels: &map[string]*string{"app": ptr.Ptr("geth")}, @@ -182,7 +207,7 @@ func TestAutomationChaos(t *testing.T) { testCase := testCase t.Run(fmt.Sprintf("Automation_%s", name), func(t *testing.T) { t.Parallel() - network := networks.MustGetSelectedNetworksFromEnv()[0] // Need a new copy of the network for each test + network := networks.MustGetSelectedNetworkConfig(config.Network)[0] // Need a new copy of the network for each test testEnvironment := environment. New(&environment.Config{ @@ -224,7 +249,7 @@ func TestAutomationChaos(t *testing.T) { if chainClient != nil { chainClient.GasStats().PrintStats() } - err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, chainClient) + err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config, chainClient) require.NoError(t, err, "Error tearing down environment") }) diff --git a/integration-tests/chaos/ocr2vrf_chaos_test.go b/integration-tests/chaos/ocr2vrf_chaos_test.go index 200114ddafb..eda60a37f3c 100644 --- a/integration-tests/chaos/ocr2vrf_chaos_test.go +++ b/integration-tests/chaos/ocr2vrf_chaos_test.go @@ -11,6 +11,7 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" @@ -26,17 +27,24 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestOCR2VRFChaos(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - loadedNetwork := networks.MustGetSelectedNetworksFromEnv()[0] + testconfig, err := tc.GetConfig("Chaos", tc.OCR2VRF) + if err != nil { + t.Fatal(err) + } + + loadedNetwork := networks.MustGetSelectedNetworkConfig(testconfig.Network)[0] defaultOCR2VRFSettings := map[string]interface{}{ "replicas": 6, "toml": networks.AddNetworkDetailedConfig( config.BaseOCR2Config, + testconfig.Pyroscope, config.DefaultOCR2VRFNetworkDetailTomlConfig, loadedNetwork, ), @@ -48,6 +56,13 @@ func TestOCR2VRFChaos(t *testing.T) { WsURLs: loadedNetwork.URLs, } + var overrideFn = func(_ interface{}, target interface{}) { + ctf_config.MustConfigOverrideChainlinkVersion(testconfig.ChainlinkImage, target) + ctf_config.MightConfigOverridePyroscopeKey(testconfig.Pyroscope, target) + } + + chainlinkCfg := chainlink.NewWithOverride(0, defaultOCR2VRFSettings, testconfig.ChainlinkImage, overrideFn) + testCases := map[string]struct { networkChart environment.ConnectedChart clChart environment.ConnectedChart @@ -65,7 +80,7 @@ func TestOCR2VRFChaos(t *testing.T) { //4. verify VRF request gets fulfilled PodChaosFailMinorityNodes: { ethereum.New(defaultOCR2VRFEthereumSettings), - chainlink.New(0, defaultOCR2VRFSettings), + chainlinkCfg, chaos.NewFailPods, &chaos.Props{ LabelsSelector: &map[string]*string{ChaosGroupMinority: ptr.Ptr("1")}, @@ -75,7 +90,7 @@ func TestOCR2VRFChaos(t *testing.T) { //todo - currently failing, need to investigate deeper //PodChaosFailMajorityNodes: { // ethereum.New(defaultOCR2VRFEthereumSettings), - // chainlink.New(0, defaultOCR2VRFSettings), + // chainlinkCfg, // chaos.NewFailPods, // &chaos.Props{ // LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")}, @@ -85,7 +100,7 @@ func TestOCR2VRFChaos(t *testing.T) { //todo - do we need these chaos tests? //PodChaosFailMajorityDB: { // ethereum.New(defaultOCR2VRFEthereumSettings), - // chainlink.New(0, defaultOCR2VRFSettings), + // chainlinkCfg, // chaos.NewFailPods, // &chaos.Props{ // LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")}, @@ -95,7 +110,7 @@ func TestOCR2VRFChaos(t *testing.T) { //}, //NetworkChaosFailMajorityNetwork: { // ethereum.New(defaultOCR2VRFEthereumSettings), - // chainlink.New(0, defaultOCR2VRFSettings), + // chainlinkCfg, // chaos.NewNetworkPartition, // &chaos.Props{ // FromLabels: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")}, @@ -105,7 +120,7 @@ func TestOCR2VRFChaos(t *testing.T) { //}, //NetworkChaosFailBlockchainNode: { // ethereum.New(defaultOCR2VRFEthereumSettings), - // chainlink.New(0, defaultOCR2VRFSettings), + // chainlinkCfg, // chaos.NewNetworkPartition, // &chaos.Props{ // FromLabels: &map[string]*string{"app": ptr.Ptr("geth")}, @@ -119,7 +134,7 @@ func TestOCR2VRFChaos(t *testing.T) { testCase := tc t.Run(fmt.Sprintf("OCR2VRF_%s", testCaseName), func(t *testing.T) { t.Parallel() - testNetwork := networks.MustGetSelectedNetworksFromEnv()[0] // Need a new copy of the network for each test + testNetwork := networks.MustGetSelectedNetworkConfig(testconfig.Network)[0] // Need a new copy of the network for each test testEnvironment := environment. New(&environment.Config{ NamespacePrefix: fmt.Sprintf( @@ -150,7 +165,7 @@ func TestOCR2VRFChaos(t *testing.T) { require.NoError(t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") t.Cleanup(func() { - err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, chainClient) + err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &testconfig, chainClient) require.NoError(t, err, "Error tearing down environment") }) diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index a59a0a028c2..97f7c67d1b9 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -3,7 +3,6 @@ package chaos import ( "fmt" "math/big" - "os" "testing" "github.com/onsi/gomega" @@ -12,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" @@ -25,8 +25,8 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) var ( @@ -51,14 +51,26 @@ var ( chaosEndRound int64 = 4 ) -func TestMain(m *testing.M) { - defaultOCRSettings["toml"] = networks.AddNetworksConfig(config.BaseOCR1Config, networks.MustGetSelectedNetworksFromEnv()[0]) - os.Exit(m.Run()) +func getDefaultOcrSettings(config *tc.TestConfig) map[string]interface{} { + defaultOCRSettings["toml"] = networks.AddNetworksConfig(baseTOML, config.Pyroscope, networks.MustGetSelectedNetworkConfig(config.Network)[0]) + return defaultAutomationSettings } func TestOCRChaos(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Chaos", tc.OCR) + if err != nil { + t.Fatal(err) + } + + var overrideFn = func(_ interface{}, target interface{}) { + ctf_config.MustConfigOverrideChainlinkVersion(config.ChainlinkImage, target) + ctf_config.MightConfigOverridePyroscopeKey(config.Pyroscope, target) + } + + chainlinkCfg := chainlink.NewWithOverride(0, getDefaultOcrSettings(&config), config.ChainlinkImage, overrideFn) + testCases := map[string]struct { networkChart environment.ConnectedChart clChart environment.ConnectedChart @@ -77,7 +89,7 @@ func TestOCRChaos(t *testing.T) { // https://github.com/smartcontractkit/chainlink-testing-framework/k8s/blob/master/README.md NetworkChaosFailMajorityNetwork: { ethereum.New(nil), - chainlink.New(0, defaultOCRSettings), + chainlinkCfg, chaos.NewNetworkPartition, &chaos.Props{ FromLabels: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")}, @@ -87,7 +99,7 @@ func TestOCRChaos(t *testing.T) { }, NetworkChaosFailBlockchainNode: { ethereum.New(nil), - chainlink.New(0, defaultOCRSettings), + chainlinkCfg, chaos.NewNetworkPartition, &chaos.Props{ FromLabels: &map[string]*string{"app": ptr.Ptr("geth")}, @@ -97,7 +109,7 @@ func TestOCRChaos(t *testing.T) { }, PodChaosFailMinorityNodes: { ethereum.New(nil), - chainlink.New(0, defaultOCRSettings), + chainlinkCfg, chaos.NewFailPods, &chaos.Props{ LabelsSelector: &map[string]*string{ChaosGroupMinority: ptr.Ptr("1")}, @@ -106,7 +118,7 @@ func TestOCRChaos(t *testing.T) { }, PodChaosFailMajorityNodes: { ethereum.New(nil), - chainlink.New(0, defaultOCRSettings), + chainlinkCfg, chaos.NewFailPods, &chaos.Props{ LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")}, @@ -115,7 +127,7 @@ func TestOCRChaos(t *testing.T) { }, PodChaosFailMajorityDB: { ethereum.New(nil), - chainlink.New(0, defaultOCRSettings), + chainlinkCfg, chaos.NewFailPods, &chaos.Props{ LabelsSelector: &map[string]*string{ChaosGroupMajority: ptr.Ptr("1")}, @@ -164,7 +176,7 @@ func TestOCRChaos(t *testing.T) { if chainClient != nil { chainClient.GasStats().PrintStats() } - err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, chainClient) + err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config, chainClient) require.NoError(t, err, "Error tearing down environment") }) diff --git a/integration-tests/client/chainlink_k8s.go b/integration-tests/client/chainlink_k8s.go index 27fd956103e..ab4ce341584 100644 --- a/integration-tests/client/chainlink_k8s.go +++ b/integration-tests/client/chainlink_k8s.go @@ -2,7 +2,6 @@ package client import ( - "fmt" "os" "regexp" @@ -42,16 +41,8 @@ func NewChainlinkK8sClient(c *ChainlinkConfig, podName, chartName string) (*Chai // Note: You need to call Run() on the test environment for changes to take effect // Note: This function is not thread safe, call from a single thread func (c *ChainlinkK8sClient) UpgradeVersion(testEnvironment *environment.Environment, newImage, newVersion string) error { - if newVersion == "" { - return fmt.Errorf("new version is empty") - } - if newImage == "" { - newImage = os.Getenv("CHAINLINK_IMAGE") - } log.Info(). Str("Chart Name", c.ChartName). - Str("Old Image", os.Getenv("CHAINLINK_IMAGE")). - Str("Old Version", os.Getenv("CHAINLINK_VERSION")). Str("New Image", newImage). Str("New Version", newVersion). Msg("Upgrading Chainlink Node") diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go index ad191d65d16..a15fcfc7aea 100644 --- a/integration-tests/contracts/ethereum_keeper_contracts.go +++ b/integration-tests/contracts/ethereum_keeper_contracts.go @@ -19,7 +19,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink/integration-tests/testreporters" cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_consumer_benchmark" @@ -42,6 +41,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_transcoder" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + "github.com/smartcontractkit/chainlink/integration-tests/testreporters" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_performance_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_counter_wrapper" diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index 1cf3bc05416..2ffd49b8776 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -163,16 +163,10 @@ func (n *ClNode) Restart(cfg *chainlink.Config) error { // UpgradeVersion restarts the cl node with new image and version func (n *ClNode) UpgradeVersion(newImage, newVersion string) error { - if newVersion == "" { - return fmt.Errorf("new version is empty") - } - if newImage == "" { - newImage = os.Getenv("CHAINLINK_IMAGE") - } n.l.Info(). Str("Name", n.ContainerName). - Str("Old Image", os.Getenv("CHAINLINK_IMAGE")). - Str("Old Version", os.Getenv("CHAINLINK_VERSION")). + Str("Old Image", newImage). + Str("Old Version", newVersion). Str("New Image", newImage). Str("New Version", newVersion). Msg("Upgrading Chainlink Node") diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index 4ffa8cb3a88..cbe2ed2d462 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "math/big" - "os" "runtime/debug" "testing" @@ -23,6 +22,8 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + + core_testconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) var ( @@ -149,14 +150,15 @@ func (te *CLClusterTestEnv) StartMockAdapter() error { return te.MockAdapter.StartContainer() } -func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count int, secretsConfig string, opts ...ClNodeOption) error { +// pass config here +func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count int, secretsConfig string, testconfig core_testconfig.GlobalTestConfig, opts ...ClNodeOption) error { if te.Cfg != nil && te.Cfg.ClCluster != nil { te.ClCluster = te.Cfg.ClCluster } else { opts = append(opts, WithSecrets(secretsConfig), WithLogStream(te.LogStream)) te.ClCluster = &ClCluster{} for i := 0; i < count; i++ { - ocrNode, err := NewClNode([]string{te.Network.Name}, os.Getenv("CHAINLINK_IMAGE"), os.Getenv("CHAINLINK_VERSION"), nodeConfig, opts...) + ocrNode, err := NewClNode([]string{te.Network.Name}, *testconfig.GetChainlinkImageConfig().Image, *testconfig.GetChainlinkImageConfig().Version, nodeConfig, opts...) if err != nil { return err } diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 336a70ded2b..6195ce22bca 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -22,6 +22,8 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) type CleanUpType string @@ -52,6 +54,7 @@ type CLTestEnvBuilder struct { chainOptionsFn []ChainOption evmClientNetworkOption []EVMClientNetworkOption ethereumNetwork *test_env.EthereumNetwork + testConfig tc.GlobalTestConfig /* funding */ ETHFunds *big.Float @@ -113,6 +116,11 @@ func (b *CLTestEnvBuilder) WithCLNodes(clNodesCount int) *CLTestEnvBuilder { return b } +func (b *CLTestEnvBuilder) WithTestConfig(cfg tc.GlobalTestConfig) *CLTestEnvBuilder { + b.testConfig = cfg + return b +} + func (b *CLTestEnvBuilder) WithCLNodeOptions(opt ...ClNodeOption) *CLTestEnvBuilder { b.clNodesOpts = append(b.clNodesOpts, opt...) return b @@ -213,6 +221,10 @@ func (b *CLTestEnvBuilder) EVMClientNetworkOptions(opts ...EVMClientNetworkOptio } func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { + if b.testConfig == nil { + return nil, fmt.Errorf("test config must be set") + } + if b.te == nil { var err error b, err = b.WithTestEnv(nil) @@ -227,7 +239,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { } if b.hasLogStream { - b.te.LogStream, err = logstream.NewLogStream(b.te.t, nil) + b.te.LogStream, err = logstream.NewLogStream(b.te.t, b.testConfig.GetLoggingConfig()) if err != nil { return nil, err } @@ -273,7 +285,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { b.l.Info().Str("Absolute path", logPath).Msg("LogStream logs folder location") } - if b.t.Failed() || os.Getenv("TEST_LOG_COLLECT") == "true" { + if b.t.Failed() || *b.testConfig.GetLoggingConfig().TestLogCollect { // we can't do much if this fails, so we just log the error in logstream _ = b.te.LogStream.FlushAndShutdown() b.te.LogStream.PrintLogTargetsLocations() @@ -303,27 +315,26 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { return nil, fmt.Errorf("cannot create nodes with custom config without nonDevNetworks") } - err = b.te.StartClCluster(b.clNodeConfig, b.clNodesCount, b.secretsConfig, b.clNodesOpts...) + err = b.te.StartClCluster(b.clNodeConfig, b.clNodesCount, b.secretsConfig, b.testConfig, b.clNodesOpts...) if err != nil { return nil, err } return b.te, nil } - networkConfig := networks.MustGetSelectedNetworksFromEnv()[0] + networkConfig := networks.MustGetSelectedNetworkConfig(b.testConfig.GetNetworkConfig())[0] var rpcProvider test_env.RpcProvider if b.ethereumNetwork != nil && networkConfig.Simulated { // TODO here we should save the ethereum network config to te.Cfg, but it doesn't exist at this point // in general it seems we have no methods for saving config to file and we only load it from file // but I don't know how that config file is to be created or whether anyone ever done that - var enCfg test_env.EthereumNetwork b.ethereumNetwork.DockerNetworkNames = []string{b.te.Network.Name} networkConfig, rpcProvider, err = b.te.StartEthereumNetwork(b.ethereumNetwork) if err != nil { return nil, err } b.te.RpcProvider = rpcProvider - b.te.PrivateEthereumConfig = &enCfg + b.te.PrivateEthereumConfig = b.ethereumNetwork } if !b.isNonEVM { @@ -387,7 +398,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { } } - err := b.te.StartClCluster(cfg, b.clNodesCount, b.secretsConfig, b.clNodesOpts...) + err := b.te.StartClCluster(cfg, b.clNodesCount, b.secretsConfig, b.testConfig, b.clNodesOpts...) if err != nil { return nil, err } diff --git a/integration-tests/example.env b/integration-tests/example.env index bbc76bb0c09..35db6263644 100644 --- a/integration-tests/example.env +++ b/integration-tests/example.env @@ -2,11 +2,8 @@ # `source ./integration-tests/.env` ########## General Test Settings ########## -export CHAINLINK_IMAGE="public.ecr.aws/chainlink/chainlink" # Image repo to pull the Chainlink image from -export CHAINLINK_VERSION="2.4.0" # Version of the Chainlink image to pull export CHAINLINK_ENV_USER="Satoshi-Nakamoto" # Name of the person running the tests (change to your own) export TEST_LOG_LEVEL="info" # info | debug | trace -export TEST_LOG_COLLECT="false" # true | false, whether to collect the test logs after the test is complete, this will always be done if the test fails, regardless of this setting ########## Soak/Chaos/Load Test Specific Settings ########## # Remote Runner @@ -19,52 +16,7 @@ export SLACK_API_KEY="xoxb-example-key" # API key used to report soak test resul export SLACK_CHANNEL="C000000000" # Channel ID for the slack bot to post test results export SLACK_USER="U000000000" # User ID of the person running the soak tests to properly notify them -# OCR Soak Test Settings -export OCR_TEST_DURATION="15m" # For an OCRv1 soak test, how long to run the test for -export OCR_CHAINLINK_NODE_FUNDING=".01" # For an OCRv1 soak test, how much ETH to send to each node -export OCR_TIME_BETWEEN_ROUNDS="1m" # For an OCRv1 soak test, how long to wait between starting new rounds - -# Node Version Upgrade Settings -export TEST_UPGRADE_IMAGE="" # Image path to use for the node version upgrade test, likely empty -export TEST_UPGRADE_VERSION="2.0.0" # Version of the Chainlink image to upgrade to for upgrade tests. Should be newer than the current version - ########## Network Settings ########## - -# If running on a live network, you must set the following values -# Select a pre-defined network(s) -export SELECTED_NETWORKS="SIMULATED" -# General private values that will be retrieved when running on non-simulated networks -export EVM_URLS="wss://evm.url,wss://other.url" # Comma-sparated list of websocket URLs to use when running on live networks -export EVM_HTTP_URLS="https://evm.url,https://other.url" # Comma-sparated list of HTTP URLs to use when running on live networks -export EVM_KEYS="private,funding,keys" # Comma-separated list of private keys to use when running on live networks - -# Specific private values retrieved when running on specified chains -# Will override the general values above if the SELECTED_NETWORKS contains the network name -# Goerli -export GOERLI_URLS="wss://goerli.io/ws" -export GOERLI_HTTP_URLS="http://goerli.io/ws" -export GOERLI_KEYS="goerli,funding,keys" -# Sepolia -export SEPOLIA_URLS="wss://sepolia.io/ws" -export SEPOLIA_HTTP_URLS="http://sepolia.io/ws" -export SEPOLIA_KEYS="sepolia,funding,keys" -# Klaytn Baobab -export KLAYTN_BAOBAB_URLS="wss://klaytn.io/ws" -export KLAYTN_BAOBAB_HTTP_URLS="http://klaytn.io/ws" -export KLAYTN_BAOBAB_KEYS="klaytn,funding,keys" -# Metis Stardust -export METIS_STARDUST_URLS="wss://metis.io/ws" -export METIS_STARDUST_HTTP_URLS="http://metis.io/ws" -export METIS_STARDUST_KEYS="metis,funding,keys" -# Arbitrum Goerli -export ARBITRUM_GOERLI_URLS="wss://arbitrum.io/ws" -export ARBITRUM_GOERLI_HTTP_URLS="http://arbitrum.io/ws" -export ARBITRUM_GOERLI_KEYS="arbitrum,funding,keys" -# Optimism Goerli -export OPTIMISM_GOERLI_URLS="wss://optimism.io/ws" -export OPTIMISM_GOERLI_HTTP_URLS="http://optimism.io/ws" -export OPTIMISM_GOERLI_KEYS="optimism,funding,keys" - # General EVM Settings, used only for quick prototyping when using GENERAL as the SELECTED_NETWORK export EVM_NAME="General EVM" export EVM_CHAIN_ID="1" diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 064a489770b..9fe026cdd97 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -7,13 +7,13 @@ replace github.com/smartcontractkit/chainlink/v2 => ../ require ( github.com/K-Phoen/grabana v0.21.17 + github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df github.com/cli/go-gh/v2 v2.0.0 github.com/ethereum/go-ethereum v1.13.8 github.com/go-resty/resty/v2 v2.7.0 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.4.0 github.com/jmoiron/sqlx v1.3.5 - github.com/kelseyhightower/envconfig v1.4.0 github.com/lib/pq v1.10.9 github.com/manifoldco/promptui v0.9.0 github.com/onsi/gomega v1.30.0 @@ -25,20 +25,22 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240118014648-1ab6a88c9429 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240123141952-a879db9d23b3 - github.com/smartcontractkit/chainlink-testing-framework v1.22.6 + github.com/smartcontractkit/chainlink-testing-framework v1.23.0 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240112202000-6359502d2ff1 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 - github.com/smartcontractkit/wasp v0.4.0 + github.com/smartcontractkit/wasp v0.4.1 github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.4 + github.com/test-go/testify v1.1.4 github.com/testcontainers/testcontainers-go v0.23.0 github.com/umbracle/ethgo v0.1.3 go.dedis.ch/kyber/v3 v3.1.0 go.uber.org/ratelimit v0.2.0 go.uber.org/zap v1.26.0 golang.org/x/sync v0.5.0 + golang.org/x/text v0.14.0 gopkg.in/guregu/null.v4 v4.0.0 ) @@ -46,7 +48,6 @@ require ( exclude github.com/hashicorp/consul v1.2.1 replace ( - // Required until https://github.com/testcontainers/testcontainers-go/pull/1971 is merged github.com/testcontainers/testcontainers-go => github.com/Tofel/testcontainers-go v0.0.0-20231130110817-e6fbf9498b56 // Pin K8s versions as their updates are highly disruptive and go mod keeps wanting to update them k8s.io/api => k8s.io/api v0.25.11 @@ -284,6 +285,7 @@ require ( github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect + github.com/kelseyhightower/envconfig v1.4.0 // indirect github.com/klauspost/compress v1.17.2 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect @@ -436,7 +438,6 @@ require ( golang.org/x/oauth2 v0.15.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/term v0.15.0 // indirect - golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.16.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect @@ -485,4 +486,7 @@ replace ( // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f + + // type func(a Label, b Label) bool of func(a, b Label) bool {…} does not match inferred type func(a Label, b Label) int for func(a E, b E) int + github.com/prometheus/prometheus => github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510 ) diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 10671c432a3..95d294e611f 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -81,19 +81,31 @@ github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/azure-sdk-for-go v65.0.0+incompatible h1:HzKLt3kIwMm4KeJYTdx9EbjRYTySD/t8i1Ee/W5EGXw= +github.com/Azure/azure-sdk-for-go v65.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1 h1:UPeCRD+XY7QlaGQte2EVI2iOcWvUYA2XY8w5T/8v0NQ= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1/go.mod h1:oGV6NlB0cvi1ZbYRR2UN44QHxWFyGk+iylgD0qaMXjA= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 h1:QM6sE5k2ZT/vI5BEe0r7mqjsUSnhVBFbOsVkEuaEfiA= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2 v2.2.1 h1:bWh0Z2rOEDfB/ywv/l0iHN1JgyazE6kW/aIA89+CEK0= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2 v2.2.1/go.mod h1:Bzf34hhAE9NSxailk8xVeLEZbUjOXcC+GnU1mMKdhLw= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= +github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= +github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= +github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= +github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= +github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= +github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk= @@ -204,6 +216,8 @@ github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYS github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= +github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -418,8 +432,8 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUn github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/digitalocean/godo v1.104.1 h1:SZNxjAsskM/su0YW9P8Wx3gU0W1Z13b6tZlYNpl5BnA= -github.com/digitalocean/godo v1.104.1/go.mod h1:VAI/L5YDzMuPRU01lEEUSQ/sp5Z//1HnnFv/RBTEdbg= +github.com/digitalocean/godo v1.99.0 h1:gUHO7n9bDaZFWvbzOum4bXE0/09ZuYA9yA8idQHX57E= +github.com/digitalocean/godo v1.99.0/go.mod h1:SsS2oXo2rznfM/nORlZ/6JaUJZFhmKTib1YhopUc8NA= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= @@ -794,8 +808,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= @@ -805,15 +819,15 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= -github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= +github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gophercloud/gophercloud v1.7.0 h1:fyJGKh0LBvIZKLvBWvQdIgkaV5yTM3Jh9EYUh+UNCAs= -github.com/gophercloud/gophercloud v1.7.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= +github.com/gophercloud/gophercloud v1.5.0 h1:cDN6XFCLKiiqvYpjQLq9AiM7RDRbIC9450WpPH+yvXo= +github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -939,8 +953,8 @@ github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= -github.com/hashicorp/nomad/api v0.0.0-20230721134942-515895c7690c h1:Nc3Mt2BAnq0/VoLEntF/nipX+K1S7pG+RgwiitSv6v0= -github.com/hashicorp/nomad/api v0.0.0-20230721134942-515895c7690c/go.mod h1:O23qLAZuCx4htdY9zBaO4cJPXgleSFEdq6D/sezGgYE= +github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e h1:sr4lujmn9heD030xx/Pd4B/JSmvRhFzuotNXaaV0WLs= +github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e/go.mod h1:O23qLAZuCx4htdY9zBaO4cJPXgleSFEdq6D/sezGgYE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= @@ -950,8 +964,8 @@ github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7H github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/henvic/httpretty v0.0.6 h1:JdzGzKZBajBfnvlMALXXMVQWxWMF/ofTy8C3/OSUTxs= github.com/henvic/httpretty v0.0.6/go.mod h1:X38wLjWXHkXT7r2+uK8LjCMne9rsuNaBLJ+5cU2/Pmo= -github.com/hetznercloud/hcloud-go/v2 v2.4.0 h1:MqlAE+w125PLvJRCpAJmEwrIxoVdUdOyuFUhE/Ukbok= -github.com/hetznercloud/hcloud-go/v2 v2.4.0/go.mod h1:l7fA5xsncFBzQTyw29/dw5Yr88yEGKKdc6BHf24ONS0= +github.com/hetznercloud/hcloud-go/v2 v2.0.0 h1:Sg1DJ+MAKvbYAqaBaq9tPbwXBS2ckPIaMtVdUjKu+4g= +github.com/hetznercloud/hcloud-go/v2 v2.0.0/go.mod h1:4iUG2NG8b61IAwNx6UsMWQ6IfIf/i1RsG0BbsKAyR5Q= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= @@ -981,8 +995,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/ionos-cloud/sdk-go/v6 v6.1.9 h1:Iq3VIXzeEbc8EbButuACgfLMiY5TPVWUPNrF+Vsddo4= -github.com/ionos-cloud/sdk-go/v6 v6.1.9/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= +github.com/ionos-cloud/sdk-go/v6 v6.1.8 h1:493wE/BkZxJf7x79UCE0cYGPZoqQcPiEBALvt7uVGY0= +github.com/ionos-cloud/sdk-go/v6 v6.1.8/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= @@ -1133,8 +1147,8 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/linode/linodego v1.23.0 h1:s0ReCZtuN9Z1IoUN9w1RLeYO1dMZUGPwOQ/IBFsBHtU= -github.com/linode/linodego v1.23.0/go.mod h1:0U7wj/UQOqBNbKv1FYTXiBUXueR8DY4HvIotwE0ENgg= +github.com/linode/linodego v1.19.0 h1:n4WJrcr9+30e9JGZ6DI0nZbm5SdAj1kSwvvt/998YUw= +github.com/linode/linodego v1.19.0/go.mod h1:XZFR+yJ9mm2kwf6itZ6SCpu+6w3KnIevV0Uu5HNWJgQ= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= @@ -1317,8 +1331,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= -github.com/ovh/go-ovh v1.4.3 h1:Gs3V823zwTFpzgGLZNI6ILS4rmxZgJwJCz54Er9LwD0= -github.com/ovh/go-ovh v1.4.3/go.mod h1:AkPXVtgwB6xlKblMjRKJJmjRp+ogrE7fz2lVgcQY8SY= +github.com/ovh/go-ovh v1.4.1 h1:VBGa5wMyQtTP7Zb+w97zRCh9sLtM/2YKRyy+MEJmWaM= +github.com/ovh/go-ovh v1.4.1/go.mod h1:6bL6pPyUT7tBfI0pqOegJgRjgjuO+mOo+MyXd1EEC0M= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1395,8 +1409,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/prometheus/prometheus v0.48.1 h1:CTszphSNTXkuCG6O0IfpKdHcJkvvnAAE1GbELKS+NFk= -github.com/prometheus/prometheus v0.48.1/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g= +github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510 h1:6ksZ7t1hNOzGPPs8DK7SvXQf6UfWzi+W5Z7PCBl8gx4= +github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510/go.mod h1:UC0TwJiF90m2T3iYPQBKnGu8gv3s55dF/EgpTq8gyvo= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/pyroscope-io/client v0.7.1 h1:yFRhj3vbgjBxehvxQmedmUWJQ4CAfCHhn+itPsuWsHw= github.com/pyroscope-io/client v0.7.1/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU= @@ -1444,8 +1458,8 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21 h1:yWfiTPwYxB0l5fGMhl/G+liULugVIHD9AU77iNLrURQ= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20 h1:a9hSJdJcd16e0HoMsnFvaHvxB3pxSD+SC7+CISp7xY0= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= @@ -1498,8 +1512,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240122152632-38444d2ad8b github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240122152632-38444d2ad8ba/go.mod h1:OZfzyayUdwsVBqxvbEMqwUntQT8HbFbgyqoudvwfVN0= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240119162652-3a7274645007 h1:KwB0H2P/gxJgt823Ku1fTcFLDKMj6zsP3wbQGlBOm4U= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240119162652-3a7274645007/go.mod h1:EbZAlb/2K6mKr26u3+3cLBe/caJaqCHw786On94C43g= -github.com/smartcontractkit/chainlink-testing-framework v1.22.6 h1:5kWMlo99RY/ys4EWGMPsEg1sfY67f5YQogI8PohdRvw= -github.com/smartcontractkit/chainlink-testing-framework v1.22.6/go.mod h1:FBRC6elqaqO8jiMZMfa3UKrvwzZhMGUtYqVTGYmfFrA= +github.com/smartcontractkit/chainlink-testing-framework v1.23.0 h1:x9xDkPCgukjU0GStjIb2x7qlLytycYujWKVLcG1YQow= +github.com/smartcontractkit/chainlink-testing-framework v1.23.0/go.mod h1:StIOdxvwd8AMO6xuBtmD6FQfJXktEn/mJJEr7728BTc= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= @@ -1512,8 +1526,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= -github.com/smartcontractkit/wasp v0.4.0 h1:N8yPxlBvoJiyE6HaDkTkwRbuOHkGgQFGEHbw36oh4jA= -github.com/smartcontractkit/wasp v0.4.0/go.mod h1:3qiofyI3pkbrc48a3CVshbMfgl74SiuPL/tm30d9Wb4= +github.com/smartcontractkit/wasp v0.4.1 h1:qgIx2s+eCwH0OaBKaHEAHUQ1Z47bAgDu+ICS9IOqvGQ= +github.com/smartcontractkit/wasp v0.4.1/go.mod h1:3qiofyI3pkbrc48a3CVshbMfgl74SiuPL/tm30d9Wb4= github.com/smartcontractkit/wsrpc v0.7.2 h1:iBXzMeg7vc5YoezIQBq896y25BARw7OKbhrb6vPbtRQ= github.com/smartcontractkit/wsrpc v0.7.2/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= diff --git a/integration-tests/k8s/connect.go b/integration-tests/k8s/connect.go index 34eafc42e24..db9ccecb174 100644 --- a/integration-tests/k8s/connect.go +++ b/integration-tests/k8s/connect.go @@ -54,7 +54,7 @@ func ConnectRemote(l zerolog.Logger) (blockchain.EVMClient, *client2.MockserverC URLs: []string{cfg.NetworkWSURL}, HTTPURLs: []string{cfg.NetworkHTTPURL}, ChainlinkTransactionLimit: 500000, - Timeout: blockchain.JSONStrDuration{Duration: 2 * time.Minute}, + Timeout: blockchain.StrDuration{Duration: 2 * time.Minute}, MinimumConfirmations: 1, GasEstimationBuffer: 10000, } diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index d2bca2e670c..49758477767 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -2,11 +2,9 @@ package automationv2_1 import ( "context" - "encoding/base64" "fmt" "math" "math/big" - "os" "strconv" "strings" "testing" @@ -26,18 +24,21 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/networks" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" contractseth "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + a_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" @@ -117,105 +118,50 @@ ListenAddresses = ["0.0.0.0:6690"]` } ) -var ( - numberofNodes, _ = strconv.Atoi(getEnv("NUMBEROFNODES", "6")) // Number of nodes in the DON - duration, _ = strconv.Atoi(getEnv("DURATION", "900")) // Test duration in seconds - blockTime, _ = strconv.Atoi(getEnv("BLOCKTIME", "1")) // Block time in seconds for geth simulated dev network - nodeFunding, _ = strconv.ParseFloat(getEnv("NODEFUNDING", "100"), 64) // Amount of native to fund each node with - - specType = getEnv("SPECTYPE", "minimum") // minimum, recommended, local specs for the test - logLevel = getEnv("LOGLEVEL", "info") // log level for the chainlink nodes - pyroscope, _ = strconv.ParseBool(getEnv("PYROSCOPE", "false")) // enable pyroscope for the chainlink nodes - prometheus, _ = strconv.ParseBool(getEnv("PROMETHEUS", "false")) // enable prometheus for the chainlink nodes - configOverride = os.Getenv("CONFIG_OVERRIDE") // config overrides for the load config -) - -type Load struct { - NumberOfEvents int64 `toml:",omitempty"` - NumberOfSpamMatchingEvents int64 `toml:",omitempty"` - NumberOfSpamNonMatchingEvents int64 `toml:",omitempty"` - CheckBurnAmount *big.Int `toml:",omitempty"` - PerformBurnAmount *big.Int `toml:",omitempty"` - UpkeepGasLimit uint32 `toml:",omitempty"` - NumberOfUpkeeps int `toml:",omitempty"` - SharedTrigger bool `toml:",omitempty"` -} - -type LoadConfig struct { - Load []Load `toml:",omitempty"` -} - -var defaultLoadConfig = LoadConfig{ - Load: []Load{ - { - NumberOfEvents: 1, - NumberOfSpamMatchingEvents: 1, - NumberOfSpamNonMatchingEvents: 0, - CheckBurnAmount: big.NewInt(0), - PerformBurnAmount: big.NewInt(0), - UpkeepGasLimit: 1_000_000, - NumberOfUpkeeps: 5, - SharedTrigger: false, - }, - { - NumberOfEvents: 1, - NumberOfSpamMatchingEvents: 0, - NumberOfSpamNonMatchingEvents: 1, - CheckBurnAmount: big.NewInt(0), - PerformBurnAmount: big.NewInt(0), - UpkeepGasLimit: 1_000_000, - NumberOfUpkeeps: 5, - SharedTrigger: true, - }}, -} - func TestLogTrigger(t *testing.T) { ctx := tests.Context(t) l := logging.GetTestLogger(t) - loadConfig := &LoadConfig{} - if configOverride != "" { - d, err := base64.StdEncoding.DecodeString(configOverride) - require.NoError(t, err, "Error decoding config override") - l.Info().Str("CONFIG_OVERRIDE", configOverride).Bytes("Decoded value", d).Msg("Decoding config override") - err = toml.Unmarshal(d, &loadConfig) - require.NoError(t, err, "Error unmarshalling config override") - } else { - loadConfig = &defaultLoadConfig + loadedTestConfig, err := tc.GetConfig("Load", tc.Automation) + if err != nil { + t.Fatal(err) } - loadConfigBytes, err := toml.Marshal(loadConfig) - require.NoError(t, err, "Error marshalling load config") + version := *loadedTestConfig.ChainlinkImage.Version + image := *loadedTestConfig.ChainlinkImage.Image l.Info().Msg("Starting automation v2.1 log trigger load test") - l.Info().Str("TEST_INPUTS", os.Getenv("TEST_INPUTS")).Int("Number of Nodes", numberofNodes). - Int("Duration", duration). - Int("Block Time", blockTime). - Str("Spec Type", specType). - Str("Log Level", logLevel). - Str("Image", os.Getenv(config.EnvVarCLImage)). - Str("Tag", os.Getenv(config.EnvVarCLTag)). - Bytes("Load Config", loadConfigBytes). + l.Info(). + Int("Number of Nodes", *loadedTestConfig.Automation.General.NumberOfNodes). + Int("Duration", *loadedTestConfig.Automation.General.Duration). + Int("Block Time", *loadedTestConfig.Automation.General.BlockTime). + Str("Spec Type", *loadedTestConfig.Automation.General.SpecType). + Str("Log Level", *loadedTestConfig.Automation.General.ChainlinkNodeLogLevel). + Str("Image", image). + Str("Tag", version). Msg("Test Config") testConfigFormat := `Number of Nodes: %d -Duration: %d -Block Time: %d -Spec Type: %s -Log Level: %s -Image: %s -Tag: %s - -Load Config: -%s` - - testConfig := fmt.Sprintf(testConfigFormat, numberofNodes, duration, - blockTime, specType, logLevel, os.Getenv(config.EnvVarCLImage), os.Getenv(config.EnvVarCLTag), string(loadConfigBytes)) + Duration: %d + Block Time: %d + Spec Type: %s + Log Level: %s + Image: %s + Tag: %s + + Load Config: + %s` + + prettyLoadConfig, err := toml.Marshal(loadedTestConfig.Automation.Load) + require.NoError(t, err, "Error marshalling load config") + + testConfig := fmt.Sprintf(testConfigFormat, *loadedTestConfig.Automation.General.NumberOfNodes, *loadedTestConfig.Automation.General.Duration, + *loadedTestConfig.Automation.General.BlockTime, *loadedTestConfig.Automation.General.SpecType, *loadedTestConfig.Automation.General.ChainlinkNodeLogLevel, image, version, string(prettyLoadConfig)) l.Info().Str("testConfig", testConfig).Msg("Test Config") - testNetwork := networks.MustGetSelectedNetworksFromEnv()[0] + testNetwork := networks.MustGetSelectedNetworkConfig(loadedTestConfig.Network)[0] testType := "load" - loadDuration := time.Duration(duration) * time.Second + loadDuration := time.Duration(*loadedTestConfig.Automation.General.Duration) * time.Second automationDefaultLinkFunds := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(10000))) //10000 LINK registrySettings := &contracts.KeeperRegistrySettings{ @@ -245,28 +191,6 @@ Load Config: PreventPodEviction: true, }) - if testEnvironment.WillUseRemoteRunner() { - key := "TEST_INPUTS" - err := os.Setenv(fmt.Sprintf("TEST_%s", key), os.Getenv(key)) - require.NoError(t, err, "failed to set the environment variable TEST_INPUTS for remote runner") - - key = config.EnvVarPyroscopeServer - err = os.Setenv(fmt.Sprintf("TEST_%s", key), os.Getenv(key)) - require.NoError(t, err, "failed to set the environment variable PYROSCOPE_SERVER for remote runner") - - key = config.EnvVarPyroscopeKey - err = os.Setenv(fmt.Sprintf("TEST_%s", key), os.Getenv(key)) - require.NoError(t, err, "failed to set the environment variable PYROSCOPE_KEY for remote runner") - - key = "GRAFANA_DASHBOARD_URL" - err = os.Setenv(fmt.Sprintf("TEST_%s", key), getEnv(key, "")) - require.NoError(t, err, "failed to set the environment variable GRAFANA_DASHBOARD_URL for remote runner") - - key = "CONFIG_OVERRIDE" - err = os.Setenv(fmt.Sprintf("TEST_%s", key), os.Getenv(key)) - require.NoError(t, err, "failed to set the environment variable CONFIG_OVERRIDE for remote runner") - } - testEnvironment. AddHelm(ethereum.New(ðereum.Props{ NetworkName: testNetwork.Name, @@ -275,7 +199,7 @@ Load Config: Values: map[string]interface{}{ "resources": gethNodeSpec, "geth": map[string]interface{}{ - "blocktime": blockTime, + "blocktime": *loadedTestConfig.Automation.General.BlockTime, "capacity": "20Gi", }, }, @@ -293,7 +217,7 @@ Load Config: dbSpec = minimumDbSpec ) - switch specType { + switch *loadedTestConfig.Automation.General.SpecType { case "recommended": nodeSpec = recNodeSpec dbSpec = recDbSpec @@ -305,28 +229,34 @@ Load Config: } - if !pyroscope { - err = os.Setenv(config.EnvVarPyroscopeServer, "") - require.NoError(t, err, "Error setting pyroscope server env var") + if *loadedTestConfig.Pyroscope.Enabled { + loadedTestConfig.Pyroscope.Environment = &testEnvironment.Cfg.Namespace } - err = os.Setenv(config.EnvVarPyroscopeEnvironment, testEnvironment.Cfg.Namespace) - require.NoError(t, err, "Error setting pyroscope environment env var") + numberOfUpkeeps := *loadedTestConfig.Automation.General.NumberOfNodes - for i := 0; i < numberofNodes+1; i++ { // +1 for the OCR boot node + for i := 0; i < numberOfUpkeeps+1; i++ { // +1 for the OCR boot node var nodeTOML string if i == 1 || i == 3 { - nodeTOML = fmt.Sprintf("%s\n\n[Log]\nLevel = \"%s\"", baseTOML, logLevel) + nodeTOML = fmt.Sprintf("%s\n\n[Log]\nLevel = \"%s\"", baseTOML, *loadedTestConfig.Automation.General.ChainlinkNodeLogLevel) } else { nodeTOML = fmt.Sprintf("%s\n\n[Log]\nLevel = \"info\"", baseTOML) } - nodeTOML = networks.AddNetworksConfig(nodeTOML, testNetwork) - testEnvironment.AddHelm(chainlink.New(i, map[string]any{ + nodeTOML = networks.AddNetworksConfig(nodeTOML, loadedTestConfig.Pyroscope, testNetwork) + + var overrideFn = func(_ interface{}, target interface{}) { + ctf_config.MustConfigOverrideChainlinkVersion(loadedTestConfig.ChainlinkImage, target) + ctf_config.MightConfigOverridePyroscopeKey(loadedTestConfig.Pyroscope, target) + } + + cd := chainlink.NewWithOverride(i, map[string]any{ "toml": nodeTOML, "chainlink": nodeSpec, "db": dbSpec, - "prometheus": prometheus, - })) + "prometheus": *loadedTestConfig.Automation.General.UsePrometheus, + }, loadedTestConfig.ChainlinkImage, overrideFn) + + testEnvironment.AddHelm(cd) } err = testEnvironment.Run() @@ -383,7 +313,7 @@ Load Config: a.SetupAutomationDeployment(t) - err = actions.FundChainlinkNodesAddress(chainlinkNodes[1:], chainClient, big.NewFloat(nodeFunding), 0) + err = actions.FundChainlinkNodesAddress(chainlinkNodes[1:], chainClient, big.NewFloat(*loadedTestConfig.Common.ChainlinkNodeFunding), 0) require.NoError(t, err, "Error funding chainlink nodes") consumerContracts := make([]contracts.KeeperConsumer, 0) @@ -406,21 +336,22 @@ Load Config: } upkeepConfigs := make([]automationv2.UpkeepConfig, 0) - loadConfigs := make([]Load, 0) + loadConfigs := make([]a_config.Load, 0) cEVMClient, err := blockchain.ConcurrentEVMClient(testNetwork, testEnvironment, chainClient, l) require.NoError(t, err, "Error building concurrent chain client") - for _, u := range loadConfig.Load { - for i := 0; i < u.NumberOfUpkeeps; i++ { + for _, u := range loadedTestConfig.Automation.Load { + for i := 0; i < *u.NumberOfUpkeeps; i++ { consumerContract, err := contractDeployer.DeployAutomationSimpleLogTriggerConsumer() require.NoError(t, err, "Error deploying automation consumer contract") consumerContracts = append(consumerContracts, consumerContract) l.Debug(). Str("Contract Address", consumerContract.Address()). Int("Number", i+1). - Int("Out Of", u.NumberOfUpkeeps). + Int("Out Of", *u.NumberOfUpkeeps). Msg("Deployed Automation Log Trigger Consumer Contract") - loadCfg := Load{ + + loadCfg := a_config.Load{ NumberOfEvents: u.NumberOfEvents, NumberOfSpamMatchingEvents: u.NumberOfSpamMatchingEvents, NumberOfSpamNonMatchingEvents: u.NumberOfSpamNonMatchingEvents, @@ -429,9 +360,10 @@ Load Config: UpkeepGasLimit: u.UpkeepGasLimit, SharedTrigger: u.SharedTrigger, } + loadConfigs = append(loadConfigs, loadCfg) - if u.SharedTrigger && i > 0 { + if *u.SharedTrigger && i > 0 { triggerAddresses = append(triggerAddresses, triggerAddresses[len(triggerAddresses)-1]) continue } @@ -442,7 +374,7 @@ Load Config: l.Debug(). Str("Contract Address", triggerContract.Address().Hex()). Int("Number", i+1). - Int("Out Of", u.NumberOfUpkeeps). + Int("Out Of", *u.NumberOfUpkeeps). Msg("Deployed Automation Log Trigger Emitter Contract") } err = chainClient.WaitForEvents() @@ -476,7 +408,7 @@ Load Config: UpkeepName: fmt.Sprintf("LogTriggerUpkeep-%d", i), EncryptedEmail: []byte("test@mail.com"), UpkeepContract: common.HexToAddress(consumerContract.Address()), - GasLimit: loadConfigs[i].UpkeepGasLimit, + GasLimit: *loadConfigs[i].UpkeepGasLimit, AdminAddress: common.HexToAddress(chainClient.GetDefaultWallet().Address()), TriggerType: uint8(1), CheckData: encodedCheckDataStruct, @@ -514,11 +446,11 @@ Load Config: for i, triggerContract := range triggerContracts { c := LogTriggerConfig{ Address: triggerContract.Address().String(), - NumberOfEvents: loadConfigs[i].NumberOfEvents, - NumberOfSpamMatchingEvents: loadConfigs[i].NumberOfSpamMatchingEvents, - NumberOfSpamNonMatchingEvents: loadConfigs[i].NumberOfSpamNonMatchingEvents, + NumberOfEvents: int64(*loadConfigs[i].NumberOfEvents), + NumberOfSpamMatchingEvents: int64(*loadConfigs[i].NumberOfSpamMatchingEvents), + NumberOfSpamNonMatchingEvents: int64(*loadConfigs[i].NumberOfSpamNonMatchingEvents), } - numberOfEventsEmittedPerSec = numberOfEventsEmittedPerSec + loadConfigs[i].NumberOfEvents + numberOfEventsEmittedPerSec = numberOfEventsEmittedPerSec + int64(*loadConfigs[i].NumberOfEvents) configs = append(configs, c) } @@ -529,7 +461,7 @@ Load Config: Str("Duration", testSetupDuration.String()). Msg("Test setup ended") - ts, err := sendSlackNotification("Started", l, testEnvironment.Cfg.Namespace, strconv.Itoa(numberofNodes), + ts, err := sendSlackNotification("Started", l, &loadedTestConfig, testEnvironment.Cfg.Namespace, strconv.Itoa(*loadedTestConfig.Automation.General.NumberOfNodes), strconv.FormatInt(startTimeTestSetup.UnixMilli(), 10), "now", []slack.Block{extraBlockWithText("\bTest Config\b\n```" + testConfig + "```")}, slack.MsgOptionBlocks()) if err != nil { @@ -770,7 +702,7 @@ Test Duration: %s` avgR, medianR, ninetyPctR, ninetyNinePctR, maximumR, len(allUpkeepDelays), len(allUpkeepDelaysFast), len(allUpkeepDelaysRecovery), numberOfEventsEmitted, eventsMissed, percentMissed, testExDuration.String()) - _, err = sendSlackNotification("Finished", l, testEnvironment.Cfg.Namespace, strconv.Itoa(numberofNodes), + _, err = sendSlackNotification("Finished", l, &loadedTestConfig, testEnvironment.Cfg.Namespace, strconv.Itoa(*loadedTestConfig.Automation.General.NumberOfNodes), strconv.FormatInt(startTimeTestSetup.UnixMilli(), 10), strconv.FormatInt(time.Now().UnixMilli(), 10), []slack.Block{extraBlockWithText("\bTest Report\b\n```" + testReport + "```")}, slack.MsgOptionTS(ts)) if err != nil { @@ -778,7 +710,7 @@ Test Duration: %s` } t.Cleanup(func() { - if err = actions.TeardownRemoteSuite(t, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, chainClient); err != nil { + if err = actions.TeardownRemoteSuite(t, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, &loadedTestConfig, chainClient); err != nil { l.Error().Err(err).Msg("Error when tearing down remote suite") } }) diff --git a/integration-tests/load/automationv2_1/helpers.go b/integration-tests/load/automationv2_1/helpers.go index 68ac909af90..bd5bfe58667 100644 --- a/integration-tests/load/automationv2_1/helpers.go +++ b/integration-tests/load/automationv2_1/helpers.go @@ -2,47 +2,37 @@ package automationv2_1 import ( "fmt" - "os" - "strings" "github.com/rs/zerolog" "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink/integration-tests/testreporters" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) -func getEnv(key, fallback string) string { - if inputs, ok := os.LookupEnv("TEST_INPUTS"); ok { - values := strings.Split(inputs, ",") - for _, value := range values { - if strings.Contains(value, key) { - return strings.Split(value, "=")[1] - } - } - } - return fallback -} - func extraBlockWithText(text string) slack.Block { return slack.NewSectionBlock(slack.NewTextBlockObject( "mrkdwn", text, false, false), nil, nil) } -func sendSlackNotification(header string, l zerolog.Logger, namespace string, numberOfNodes, +func sendSlackNotification(header string, l zerolog.Logger, config *tc.TestConfig, namespace string, numberOfNodes, startingTime string, endingTime string, extraBlocks []slack.Block, msgOption slack.MsgOption) (string, error) { slackClient := slack.New(reportModel.SlackAPIKey) headerText := ":chainlink-keepers: Automation Load Test " + header + " :white_check_mark:" - formattedDashboardUrl := fmt.Sprintf("%s?orgId=1&from=%s&to=%s&var-namespace=%s&var-number_of_nodes=%s", testreporters.DashboardUrl, startingTime, endingTime, namespace, numberOfNodes) - l.Info().Str("Dashboard", formattedDashboardUrl).Msg("Dashboard URL") + grafanaUrl, err := config.GetGrafanaBaseURL() + if err != nil { + return "", err + } - pyroscopeServer := os.Getenv(config.EnvVarPyroscopeServer) - pyroscopeEnvironment := os.Getenv(config.EnvVarPyroscopeEnvironment) + dashboardUrl, err := config.GetGrafanaDashboardURL() + if err != nil { + return "", err + } - formattedPyroscopeUrl := fmt.Sprintf("%s/?query=chainlink-node.cpu{Environment=\"%s\"}&from=%s&to=%s", pyroscopeServer, pyroscopeEnvironment, startingTime, endingTime) + formattedDashboardUrl := fmt.Sprintf("%s%s?orgId=1&from=%s&to=%s&var-namespace=%s&var-number_of_nodes=%s", grafanaUrl, dashboardUrl, startingTime, endingTime, namespace, numberOfNodes) + l.Info().Str("Dashboard", formattedDashboardUrl).Msg("Dashboard URL") var notificationBlocks []slack.Block @@ -51,7 +41,11 @@ func sendSlackNotification(header string, l zerolog.Logger, namespace string, nu notificationBlocks = append(notificationBlocks, slack.NewContextBlock("context_block", slack.NewTextBlockObject("plain_text", namespace, false, false))) notificationBlocks = append(notificationBlocks, slack.NewDividerBlock()) - if pyroscopeServer != "" { + if *config.Pyroscope.Enabled { + pyroscopeServer := *config.Pyroscope.ServerUrl + pyroscopeEnvironment := *config.Pyroscope.Environment + + formattedPyroscopeUrl := fmt.Sprintf("%s/?query=chainlink-node.cpu{Environment=\"%s\"}&from=%s&to=%s", pyroscopeServer, pyroscopeEnvironment, startingTime, endingTime) l.Info().Str("Pyroscope", formattedPyroscopeUrl).Msg("Dashboard URL") notificationBlocks = append(notificationBlocks, slack.NewSectionBlock(slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("<%s|Pyroscope>", diff --git a/integration-tests/load/functions/config.go b/integration-tests/load/functions/config.go deleted file mode 100644 index d34e8a9f1eb..00000000000 --- a/integration-tests/load/functions/config.go +++ /dev/null @@ -1,125 +0,0 @@ -package loadfunctions - -import ( - "fmt" - "math/big" - "os" - - "github.com/pelletier/go-toml/v2" - "github.com/rs/zerolog/log" - - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" -) - -const ( - DefaultConfigFilename = "config.toml" - - ErrReadPerfConfig = "failed to read TOML config for performance tests" - ErrUnmarshalPerfConfig = "failed to unmarshal TOML config for performance tests" -) - -type PerformanceConfig struct { - Soak *Soak `toml:"Soak"` - SecretsSoak *SecretsSoak `toml:"SecretsSoak"` - RealSoak *RealSoak `toml:"RealSoak"` - Stress *Stress `toml:"Stress"` - SecretsStress *SecretsStress `toml:"SecretsStress"` - RealStress *RealStress `toml:"RealStress"` - GatewayListSoak *GatewayListSoak `toml:"GatewayListSoak"` - GatewaySetSoak *GatewaySetSoak `toml:"GatewaySetSoak"` - Common *Common `toml:"Common"` - MumbaiPrivateKey string -} - -type Common struct { - Funding - LINKTokenAddr string `toml:"link_token_addr"` - Coordinator string `toml:"coordinator_addr"` - Router string `toml:"router_addr"` - LoadTestClient string `toml:"client_addr"` - SubscriptionID uint64 `toml:"subscription_id"` - DONID string `toml:"don_id"` - GatewayURL string `toml:"gateway_url"` - Receiver string `toml:"receiver"` - FunctionsCallPayloadHTTP string `toml:"functions_call_payload_http"` - FunctionsCallPayloadWithSecrets string `toml:"functions_call_payload_with_secrets"` - FunctionsCallPayloadReal string `toml:"functions_call_payload_real"` - SecretsSlotID uint8 `toml:"secrets_slot_id"` - SecretsVersionID uint64 `toml:"secrets_version_id"` - // Secrets these are for CI secrets - Secrets string `toml:"secrets"` -} - -type Funding struct { - NodeFunds *big.Float `toml:"node_funds"` - SubFunds *big.Int `toml:"sub_funds"` -} - -type Soak struct { - RPS int64 `toml:"rps"` - RequestsPerCall uint32 `toml:"requests_per_call"` - Duration *commonconfig.Duration `toml:"duration"` -} - -type SecretsSoak struct { - RPS int64 `toml:"rps"` - RequestsPerCall uint32 `toml:"requests_per_call"` - Duration *commonconfig.Duration `toml:"duration"` -} - -type RealSoak struct { - RPS int64 `toml:"rps"` - RequestsPerCall uint32 `toml:"requests_per_call"` - Duration *commonconfig.Duration `toml:"duration"` -} - -type Stress struct { - RPS int64 `toml:"rps"` - RequestsPerCall uint32 `toml:"requests_per_call"` - Duration *commonconfig.Duration `toml:"duration"` -} - -type SecretsStress struct { - RPS int64 `toml:"rps"` - RequestsPerCall uint32 `toml:"requests_per_call"` - Duration *commonconfig.Duration `toml:"duration"` -} - -type RealStress struct { - RPS int64 `toml:"rps"` - RequestsPerCall uint32 `toml:"requests_per_call"` - Duration *commonconfig.Duration `toml:"duration"` -} - -type GatewayListSoak struct { - RPS int64 `toml:"rps"` - Duration *commonconfig.Duration `toml:"duration"` -} - -type GatewaySetSoak struct { - RPS int64 `toml:"rps"` - Duration *commonconfig.Duration `toml:"duration"` -} - -func ReadConfig() (*PerformanceConfig, error) { - var cfg *PerformanceConfig - d, err := os.ReadFile(DefaultConfigFilename) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err) - } - err = toml.Unmarshal(d, &cfg) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrUnmarshalPerfConfig, err) - } - log.Debug().Interface("PerformanceConfig", cfg).Msg("Parsed performance config") - mpk := os.Getenv("MUMBAI_KEYS") - murls := os.Getenv("MUMBAI_URLS") - snet := os.Getenv("SELECTED_NETWORKS") - if mpk == "" || murls == "" || snet == "" { - return nil, fmt.Errorf( - "ensure variables are set:\nMUMBAI_KEYS variable, private keys, comma separated\nSELECTED_NETWORKS=MUMBAI\nMUMBAI_URLS variable, websocket urls, comma separated", - ) - } - cfg.MumbaiPrivateKey = mpk - return cfg, nil -} diff --git a/integration-tests/load/functions/functions_test.go b/integration-tests/load/functions/functions_test.go index dc52846d3c9..d3b82cde33b 100644 --- a/integration-tests/load/functions/functions_test.go +++ b/integration-tests/load/functions/functions_test.go @@ -6,12 +6,15 @@ import ( "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestFunctionsLoad(t *testing.T) { - cfg, err := ReadConfig() - require.NoError(t, err) - ft, err := SetupLocalLoadTestEnv(cfg) + generalConfig, err := tc.GetConfig(tc.NoKey, tc.Functions) + require.NoError(t, err, "failed to get config") + + ft, err := SetupLocalLoadTestEnv(&generalConfig, &generalConfig) require.NoError(t, err) ft.EVMClient.ParallelTransactions(false) @@ -20,10 +23,14 @@ func TestFunctionsLoad(t *testing.T) { "commit": "functions_healthcheck", } - MonitorLoadStats(t, ft, labels) + MonitorLoadStats(t, ft, labels, &generalConfig) t.Run("mumbai functions soak test http", func(t *testing.T) { - _, err := wasp.NewProfile(). + config, err := tc.GetConfig("Soak", tc.Functions) + require.NoError(t, err, "failed to get config") + cfg := config.Functions + cfgl := config.Logging.Loki + _, err = wasp.NewProfile(). Add(wasp.NewGenerator(&wasp.Config{ T: t, LoadType: wasp.RPS, @@ -31,28 +38,32 @@ func TestFunctionsLoad(t *testing.T) { RateLimitUnitDuration: 5 * time.Second, CallTimeout: 3 * time.Minute, Schedule: wasp.Plain( - cfg.Soak.RPS, - cfg.Soak.Duration.Duration(), + *cfg.Performance.RPS, + cfg.Performance.Duration.Duration, ), Gun: NewSingleFunctionCallGun( ft, ModeHTTPPayload, - cfg.Soak.RequestsPerCall, - cfg.Common.FunctionsCallPayloadHTTP, - cfg.Common.SecretsSlotID, - cfg.Common.SecretsVersionID, + *cfg.Performance.RequestsPerCall, + *cfg.Common.FunctionsCallPayloadHTTP, + *cfg.Common.SecretsSlotID, + *cfg.Common.SecretsVersionID, []string{}, - cfg.Common.SubscriptionID, - StringToByte32(cfg.Common.DONID), + *cfg.Common.SubscriptionID, + StringToByte32(*cfg.Common.DONID), ), Labels: labels, - LokiConfig: wasp.NewEnvLokiConfig(), + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), })). Run(true) require.NoError(t, err) }) t.Run("mumbai functions stress test http", func(t *testing.T) { + config, err := tc.GetConfig("Stress", tc.Functions) + require.NoError(t, err, "failed to get config") + cfg := config.Functions + cfgl := config.Logging.Loki _, err = wasp.NewProfile(). Add(wasp.NewGenerator(&wasp.Config{ T: t, @@ -61,29 +72,33 @@ func TestFunctionsLoad(t *testing.T) { RateLimitUnitDuration: 5 * time.Second, CallTimeout: 3 * time.Minute, Schedule: wasp.Plain( - cfg.Stress.RPS, - cfg.Stress.Duration.Duration(), + *cfg.Performance.RPS, + cfg.Performance.Duration.Duration, ), Gun: NewSingleFunctionCallGun( ft, ModeHTTPPayload, - cfg.Stress.RequestsPerCall, - cfg.Common.FunctionsCallPayloadHTTP, - cfg.Common.SecretsSlotID, - cfg.Common.SecretsVersionID, + *cfg.Performance.RequestsPerCall, + *cfg.Common.FunctionsCallPayloadHTTP, + *cfg.Common.SecretsSlotID, + *cfg.Common.SecretsVersionID, []string{}, - cfg.Common.SubscriptionID, - StringToByte32(cfg.Common.DONID), + *cfg.Common.SubscriptionID, + StringToByte32(*cfg.Common.DONID), ), Labels: labels, - LokiConfig: wasp.NewEnvLokiConfig(), + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), })). Run(true) require.NoError(t, err) }) t.Run("mumbai functions soak test only secrets", func(t *testing.T) { - _, err := wasp.NewProfile(). + config, err := tc.GetConfig("SecretsSoak", tc.Functions) + require.NoError(t, err, "failed to get config") + cfg := config.Functions + cfgl := config.Logging.Loki + _, err = wasp.NewProfile(). Add(wasp.NewGenerator(&wasp.Config{ T: t, LoadType: wasp.RPS, @@ -91,28 +106,32 @@ func TestFunctionsLoad(t *testing.T) { RateLimitUnitDuration: 5 * time.Second, CallTimeout: 3 * time.Minute, Schedule: wasp.Plain( - cfg.SecretsSoak.RPS, - cfg.SecretsSoak.Duration.Duration(), + *cfg.Performance.RPS, + cfg.Performance.Duration.Duration, ), Gun: NewSingleFunctionCallGun( ft, ModeSecretsOnlyPayload, - cfg.SecretsSoak.RequestsPerCall, - cfg.Common.FunctionsCallPayloadWithSecrets, - cfg.Common.SecretsSlotID, - cfg.Common.SecretsVersionID, + *cfg.Performance.RequestsPerCall, + *cfg.Common.FunctionsCallPayloadWithSecrets, + *cfg.Common.SecretsSlotID, + *cfg.Common.SecretsVersionID, []string{}, - cfg.Common.SubscriptionID, - StringToByte32(cfg.Common.DONID), + *cfg.Common.SubscriptionID, + StringToByte32(*cfg.Common.DONID), ), Labels: labels, - LokiConfig: wasp.NewEnvLokiConfig(), + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), })). Run(true) require.NoError(t, err) }) t.Run("mumbai functions stress test only secrets", func(t *testing.T) { + config, err := tc.GetConfig("SecretsStress", tc.Functions) + require.NoError(t, err, "failed to get config") + cfg := config.Functions + cfgl := config.Logging.Loki _, err = wasp.NewProfile(). Add(wasp.NewGenerator(&wasp.Config{ T: t, @@ -121,29 +140,33 @@ func TestFunctionsLoad(t *testing.T) { RateLimitUnitDuration: 5 * time.Second, CallTimeout: 3 * time.Minute, Schedule: wasp.Plain( - cfg.SecretsStress.RPS, - cfg.SecretsStress.Duration.Duration(), + *cfg.Performance.RPS, + cfg.Performance.Duration.Duration, ), Gun: NewSingleFunctionCallGun( ft, ModeSecretsOnlyPayload, - cfg.SecretsStress.RequestsPerCall, - cfg.Common.FunctionsCallPayloadWithSecrets, - cfg.Common.SecretsSlotID, - cfg.Common.SecretsVersionID, + *cfg.Performance.RequestsPerCall, + *cfg.Common.FunctionsCallPayloadWithSecrets, + *cfg.Common.SecretsSlotID, + *cfg.Common.SecretsVersionID, []string{}, - cfg.Common.SubscriptionID, - StringToByte32(cfg.Common.DONID), + *cfg.Common.SubscriptionID, + StringToByte32(*cfg.Common.DONID), ), Labels: labels, - LokiConfig: wasp.NewEnvLokiConfig(), + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), })). Run(true) require.NoError(t, err) }) t.Run("mumbai functions soak test real", func(t *testing.T) { - _, err := wasp.NewProfile(). + config, err := tc.GetConfig("RealSoak", tc.Functions) + require.NoError(t, err, "failed to get config") + cfg := config.Functions + cfgl := config.Logging.Loki + _, err = wasp.NewProfile(). Add(wasp.NewGenerator(&wasp.Config{ T: t, LoadType: wasp.RPS, @@ -151,28 +174,32 @@ func TestFunctionsLoad(t *testing.T) { RateLimitUnitDuration: 5 * time.Second, CallTimeout: 3 * time.Minute, Schedule: wasp.Plain( - cfg.RealSoak.RPS, - cfg.RealSoak.Duration.Duration(), + *cfg.Performance.RPS, + cfg.Performance.Duration.Duration, ), Gun: NewSingleFunctionCallGun( ft, ModeReal, - cfg.RealSoak.RequestsPerCall, - cfg.Common.FunctionsCallPayloadReal, - cfg.Common.SecretsSlotID, - cfg.Common.SecretsVersionID, + *cfg.Performance.RequestsPerCall, + *cfg.Common.FunctionsCallPayloadReal, + *cfg.Common.SecretsSlotID, + *cfg.Common.SecretsVersionID, []string{"1", "2", "3", "4"}, - cfg.Common.SubscriptionID, - StringToByte32(cfg.Common.DONID), + *cfg.Common.SubscriptionID, + StringToByte32(*cfg.Common.DONID), ), Labels: labels, - LokiConfig: wasp.NewEnvLokiConfig(), + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), })). Run(true) require.NoError(t, err) }) t.Run("mumbai functions stress test real", func(t *testing.T) { + config, err := tc.GetConfig("RealStress", tc.Functions) + require.NoError(t, err, "failed to get config") + cfg := config.Functions + cfgl := config.Logging.Loki _, err = wasp.NewProfile(). Add(wasp.NewGenerator(&wasp.Config{ T: t, @@ -181,22 +208,22 @@ func TestFunctionsLoad(t *testing.T) { RateLimitUnitDuration: 5 * time.Second, CallTimeout: 3 * time.Minute, Schedule: wasp.Plain( - cfg.RealStress.RPS, - cfg.RealStress.Duration.Duration(), + *cfg.Performance.RPS, + cfg.Performance.Duration.Duration, ), Gun: NewSingleFunctionCallGun( ft, ModeReal, - cfg.RealStress.RequestsPerCall, - cfg.Common.FunctionsCallPayloadReal, - cfg.Common.SecretsSlotID, - cfg.Common.SecretsVersionID, + *cfg.Performance.RequestsPerCall, + *cfg.Common.FunctionsCallPayloadReal, + *cfg.Common.SecretsSlotID, + *cfg.Common.SecretsVersionID, []string{"1", "2", "3", "4"}, - cfg.Common.SubscriptionID, - StringToByte32(cfg.Common.DONID), + *cfg.Common.SubscriptionID, + StringToByte32(*cfg.Common.DONID), ), Labels: labels, - LokiConfig: wasp.NewEnvLokiConfig(), + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), })). Run(true) require.NoError(t, err) diff --git a/integration-tests/load/functions/gateway_gun.go b/integration-tests/load/functions/gateway_gun.go index 62fe80ed02c..cc6132e94e7 100644 --- a/integration-tests/load/functions/gateway_gun.go +++ b/integration-tests/load/functions/gateway_gun.go @@ -4,7 +4,6 @@ import ( "crypto/ecdsa" "fmt" "math/rand" - "os" "strconv" "time" @@ -12,12 +11,14 @@ import ( "github.com/rs/zerolog/log" "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy" "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink/integration-tests/types" ) /* SingleFunctionCallGun is a gun that constantly requests randomness for one feed */ type GatewaySecretsSetGun struct { - Cfg *PerformanceConfig + Cfg types.FunctionsTestConfig Resty *resty.Client SlotID uint Method string @@ -26,7 +27,7 @@ type GatewaySecretsSetGun struct { DONPublicKey []byte } -func NewGatewaySecretsSetGun(cfg *PerformanceConfig, method string, pKey *ecdsa.PrivateKey, tdh2PubKey *tdh2easy.PublicKey, donPubKey []byte) *GatewaySecretsSetGun { +func NewGatewaySecretsSetGun(cfg types.FunctionsTestConfig, method string, pKey *ecdsa.PrivateKey, tdh2PubKey *tdh2easy.PublicKey, donPubKey []byte) *GatewaySecretsSetGun { return &GatewaySecretsSetGun{ Cfg: cfg, Resty: resty.New(), @@ -59,12 +60,18 @@ func callSecretsSet(m *GatewaySecretsSetGun) *wasp.Response { if err != nil { return &wasp.Response{Error: err.Error(), Failed: true} } + network := m.Cfg.GetNetworkConfig().SelectedNetworks[0] + if len(m.Cfg.GetNetworkConfig().WalletKeys[network]) < 1 { + panic(fmt.Sprintf("no wallet keys found for %s", network)) + } + + cfg := m.Cfg.GetFunctionsConfig() _, _, err = UploadS4Secrets(m.Resty, &S4SecretsCfg{ - GatewayURL: m.Cfg.Common.GatewayURL, - PrivateKey: os.Getenv("MUMBAI_KEYS"), + GatewayURL: *cfg.Common.GatewayURL, + PrivateKey: m.Cfg.GetNetworkConfig().WalletKeys[network][0], MessageID: randNum, Method: "secrets_set", - DonID: m.Cfg.Common.DONID, + DonID: *cfg.Common.DONID, S4SetSlotID: randSlot, S4SetVersion: version, S4SetExpirationPeriod: expiration, @@ -81,13 +88,18 @@ func callSecretsList(m *GatewaySecretsSetGun) *wasp.Response { randSlot := uint(rand.Intn(5)) version := uint64(time.Now().UnixNano()) expiration := int64(60 * 60 * 1000) + network := m.Cfg.GetNetworkConfig().SelectedNetworks[0] + if len(m.Cfg.GetNetworkConfig().WalletKeys[network]) < 1 { + panic(fmt.Sprintf("no wallet keys found for %s", network)) + } + cfg := m.Cfg.GetFunctionsConfig() if err := ListS4Secrets(m.Resty, &S4SecretsCfg{ - GatewayURL: fmt.Sprintf(m.Cfg.Common.GatewayURL), - RecieverAddr: m.Cfg.Common.Receiver, - PrivateKey: os.Getenv("MUMBAI_KEYS"), + GatewayURL: *cfg.Common.GatewayURL, + RecieverAddr: *cfg.Common.Receiver, + PrivateKey: m.Cfg.GetNetworkConfig().WalletKeys[network][0], MessageID: randNum, Method: m.Method, - DonID: m.Cfg.Common.DONID, + DonID: *cfg.Common.DONID, S4SetSlotID: randSlot, S4SetVersion: version, S4SetExpirationPeriod: expiration, diff --git a/integration-tests/load/functions/gateway_test.go b/integration-tests/load/functions/gateway_test.go index c8e63f92f2b..be5d148386c 100644 --- a/integration-tests/load/functions/gateway_test.go +++ b/integration-tests/load/functions/gateway_test.go @@ -6,13 +6,17 @@ import ( "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" ) func TestGatewayLoad(t *testing.T) { - cfg, err := ReadConfig() + listConfig, err := tc.GetConfig("GatewayList", tc.Functions) require.NoError(t, err) - ft, err := SetupLocalLoadTestEnv(cfg) + cfgl := listConfig.Logging.Loki + + require.NoError(t, err) + ft, err := SetupLocalLoadTestEnv(&listConfig, &listConfig) require.NoError(t, err) ft.EVMClient.ParallelTransactions(false) @@ -25,36 +29,39 @@ func TestGatewayLoad(t *testing.T) { LoadType: wasp.RPS, GenName: functions.MethodSecretsList, Schedule: wasp.Plain( - cfg.GatewayListSoak.RPS, - cfg.GatewayListSoak.Duration.Duration(), + *listConfig.Functions.Performance.RPS, + listConfig.Functions.Performance.Duration.Duration, ), Gun: NewGatewaySecretsSetGun( - cfg, + &listConfig, functions.MethodSecretsList, ft.EthereumPrivateKey, ft.ThresholdPublicKey, ft.DONPublicKey, ), Labels: labels, - LokiConfig: wasp.NewEnvLokiConfig(), + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), } + setConfig, err := tc.GetConfig("GatewaySet", tc.Functions) + require.NoError(t, err) + secretsSetCfg := &wasp.Config{ LoadType: wasp.RPS, GenName: functions.MethodSecretsSet, Schedule: wasp.Plain( - cfg.GatewaySetSoak.RPS, - cfg.GatewaySetSoak.Duration.Duration(), + *setConfig.Functions.Performance.RPS, + setConfig.Functions.Performance.Duration.Duration, ), Gun: NewGatewaySecretsSetGun( - cfg, + &setConfig, functions.MethodSecretsSet, ft.EthereumPrivateKey, ft.ThresholdPublicKey, ft.DONPublicKey, ), Labels: labels, - LokiConfig: wasp.NewEnvLokiConfig(), + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), } t.Run("gateway secrets list soak test", func(t *testing.T) { diff --git a/integration-tests/load/functions/onchain_monitoring.go b/integration-tests/load/functions/onchain_monitoring.go index c4b4bdb78c0..12a10ce0042 100644 --- a/integration-tests/load/functions/onchain_monitoring.go +++ b/integration-tests/load/functions/onchain_monitoring.go @@ -6,6 +6,8 @@ import ( "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) /* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */ @@ -23,7 +25,7 @@ type LoadStats struct { Empty uint32 } -func MonitorLoadStats(t *testing.T, ft *FunctionsTest, labels map[string]string) { +func MonitorLoadStats(t *testing.T, ft *FunctionsTest, labels map[string]string, config tc.GlobalTestConfig) { go func() { updatedLabels := make(map[string]string) for k, v := range labels { @@ -32,7 +34,9 @@ func MonitorLoadStats(t *testing.T, ft *FunctionsTest, labels map[string]string) updatedLabels["type"] = LokiTypeLabel updatedLabels["go_test_name"] = t.Name() updatedLabels["gen_name"] = "performance" - lc, err := wasp.NewLokiClient(wasp.NewEnvLokiConfig()) + cfgl := config.GetLoggingConfig().Loki + lokiConfig := wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken) + lc, err := wasp.NewLokiClient(lokiConfig) if err != nil { log.Error().Err(err).Msg(ErrLokiClient) return @@ -46,16 +50,20 @@ func MonitorLoadStats(t *testing.T, ft *FunctionsTest, labels map[string]string) if err != nil { log.Error().Err(err).Msg(ErrMetrics) } - log.Info(). - Hex("LastReqID", []byte(stats.LastRequestID)). - Str("LastResponse", stats.LastResponse). - Str("LastError", stats.LastError). - Uint32("Total", stats.Total). - Uint32("Succeeded", stats.Succeeded). - Uint32("Errored", stats.Errored). - Uint32("Empty", stats.Empty).Msg("On-chain stats for load test client") - if err := lc.HandleStruct(wasp.LabelsMapToModel(updatedLabels), time.Now(), stats); err != nil { - log.Error().Err(err).Msg(ErrLokiPush) + if stats != nil { + log.Info(). + Hex("LastReqID", []byte(stats.LastRequestID)). + Str("LastResponse", stats.LastResponse). + Str("LastError", stats.LastError). + Uint32("Total", stats.Total). + Uint32("Succeeded", stats.Succeeded). + Uint32("Errored", stats.Errored). + Uint32("Empty", stats.Empty).Msg("On-chain stats for load test client") + if err := lc.HandleStruct(wasp.LabelsMapToModel(updatedLabels), time.Now(), stats); err != nil { + log.Error().Err(err).Msg(ErrLokiPush) + } + } else { + log.Warn().Msg("No stats to push to Loki") } } }() diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index e96eac3cf82..e6711907592 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -5,7 +5,6 @@ import ( "fmt" "math/big" mrand "math/rand" - "os" "strconv" "time" @@ -18,6 +17,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + "github.com/smartcontractkit/chainlink/integration-tests/types" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) @@ -50,8 +51,9 @@ type S4SecretsCfg struct { S4SetPayload string } -func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*FunctionsTest, error) { - bc, err := blockchain.NewEVMClientFromNetwork(networks.MustGetSelectedNetworksFromEnv()[0], log.Logger) +func SetupLocalLoadTestEnv(globalConfig tc.GlobalTestConfig, functionsConfig types.FunctionsTestConfig) (*FunctionsTest, error) { + selectedNetwork := networks.MustGetSelectedNetworkConfig(globalConfig.GetNetworkConfig())[0] + bc, err := blockchain.NewEVMClientFromNetwork(selectedNetwork, log.Logger) if err != nil { return nil, err } @@ -67,28 +69,31 @@ func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*FunctionsTest, error) { if err != nil { return nil, err } - lt, err := cl.LoadLINKToken(cfg.Common.LINKTokenAddr) + + cfg := functionsConfig.GetFunctionsConfig() + + lt, err := cl.LoadLINKToken(*cfg.Common.LINKTokenAddr) if err != nil { return nil, err } - coord, err := cl.LoadFunctionsCoordinator(cfg.Common.Coordinator) + coord, err := cl.LoadFunctionsCoordinator(*cfg.Common.Coordinator) if err != nil { return nil, err } - router, err := cl.LoadFunctionsRouter(cfg.Common.Router) + router, err := cl.LoadFunctionsRouter(*cfg.Common.Router) if err != nil { return nil, err } var loadTestClient contracts.FunctionsLoadTestClient - if cfg.Common.LoadTestClient != "" { - loadTestClient, err = cl.LoadFunctionsLoadTestClient(cfg.Common.LoadTestClient) + if cfg.Common.LoadTestClient != nil && *cfg.Common.LoadTestClient != "" { + loadTestClient, err = cl.LoadFunctionsLoadTestClient(*cfg.Common.LoadTestClient) } else { - loadTestClient, err = cd.DeployFunctionsLoadTestClient(cfg.Common.Router) + loadTestClient, err = cd.DeployFunctionsLoadTestClient(*cfg.Common.Router) } if err != nil { return nil, err } - if cfg.Common.SubscriptionID == 0 { + if cfg.Common.SubscriptionID == nil { log.Info().Msg("Creating new subscription") subID, err := router.CreateSubscriptionWithConsumer(loadTestClient.Address()) if err != nil { @@ -98,13 +103,13 @@ func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*FunctionsTest, error) { if err != nil { return nil, fmt.Errorf("failed to encode subscription ID for funding: %w", err) } - _, err = lt.TransferAndCall(router.Address(), big.NewInt(0).Mul(cfg.Common.Funding.SubFunds, big.NewInt(1e18)), encodedSubId) + _, err = lt.TransferAndCall(router.Address(), big.NewInt(0).Mul(cfg.Common.SubFunds, big.NewInt(1e18)), encodedSubId) if err != nil { return nil, fmt.Errorf("failed to transferAndCall router, LINK funding: %w", err) } - cfg.Common.SubscriptionID = subID + cfg.Common.SubscriptionID = &subID } - pKey, pubKey, err := parseEthereumPrivateKey(os.Getenv("MUMBAI_KEYS")) + pKey, pubKey, err := parseEthereumPrivateKey(selectedNetwork.PrivateKeys[0]) if err != nil { return nil, fmt.Errorf("failed to load Ethereum private key: %w", err) } @@ -123,17 +128,17 @@ func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*FunctionsTest, error) { return nil, fmt.Errorf("failed to unmarshal tdh2 public key: %w", err) } var encryptedSecrets string - if cfg.Common.Secrets != "" { - encryptedSecrets, err = EncryptS4Secrets(pKey, tdh2pk, donPubKey, cfg.Common.Secrets) + if cfg.Common.Secrets != nil && *cfg.Common.Secrets != "" { + encryptedSecrets, err = EncryptS4Secrets(pKey, tdh2pk, donPubKey, *cfg.Common.Secrets) if err != nil { return nil, fmt.Errorf("failed to generate tdh2 secrets: %w", err) } slotID, slotVersion, err := UploadS4Secrets(resty.New(), &S4SecretsCfg{ - GatewayURL: cfg.Common.GatewayURL, - PrivateKey: cfg.MumbaiPrivateKey, + GatewayURL: *cfg.Common.GatewayURL, + PrivateKey: selectedNetwork.PrivateKeys[0], MessageID: strconv.Itoa(mrand.Intn(100000-1) + 1), Method: "secrets_set", - DonID: cfg.Common.DONID, + DonID: *cfg.Common.DONID, S4SetSlotID: uint(mrand.Intn(5)), S4SetVersion: uint64(time.Now().UnixNano()), S4SetExpirationPeriod: 60 * 60 * 1000, @@ -142,8 +147,8 @@ func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*FunctionsTest, error) { if err != nil { return nil, fmt.Errorf("failed to upload secrets to S4: %w", err) } - cfg.Common.SecretsSlotID = slotID - cfg.Common.SecretsVersionID = slotVersion + cfg.Common.SecretsSlotID = &slotID + cfg.Common.SecretsVersionID = &slotVersion log.Info(). Uint8("SlotID", slotID). Uint64("SlotVersion", slotVersion). diff --git a/integration-tests/load/ocr/config.go b/integration-tests/load/ocr/config.go deleted file mode 100644 index 4b324210b09..00000000000 --- a/integration-tests/load/ocr/config.go +++ /dev/null @@ -1,72 +0,0 @@ -package ocr - -import ( - "encoding/base64" - "fmt" - "os" - - "github.com/pelletier/go-toml/v2" - "github.com/rs/zerolog/log" - - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" -) - -const ( - DefaultConfigFilename = "config.toml" - ErrReadPerfConfig = "failed to read TOML config for performance tests" - ErrUnmarshalPerfConfig = "failed to unmarshal TOML config for performance tests" -) - -type PerformanceConfig struct { - Load *Load `toml:"Load"` - Volume *Volume `toml:"Volume"` - Common *Common `toml:"Common"` -} - -type Common struct { - ETHFunds int `toml:"eth_funds"` -} - -type Load struct { - TestDuration *commonconfig.Duration `toml:"test_duration"` - Rate int64 `toml:"rate"` - RateLimitUnitDuration *commonconfig.Duration `toml:"rate_limit_unit_duration"` - VerificationInterval *commonconfig.Duration `toml:"verification_interval"` - VerificationTimeout *commonconfig.Duration `toml:"verification_timeout"` - EAChangeInterval *commonconfig.Duration `toml:"ea_change_interval"` -} - -type Volume struct { - TestDuration *commonconfig.Duration `toml:"test_duration"` - Rate int64 `toml:"rate"` - VURequestsPerUnit int `toml:"vu_requests_per_unit"` - RateLimitUnitDuration *commonconfig.Duration `toml:"rate_limit_unit_duration"` - VerificationInterval *commonconfig.Duration `toml:"verification_interval"` - VerificationTimeout *commonconfig.Duration `toml:"verification_timeout"` - EAChangeInterval *commonconfig.Duration `toml:"ea_change_interval"` -} - -func ReadConfig() (*PerformanceConfig, error) { - var cfg *PerformanceConfig - rawConfig := os.Getenv("CONFIG") - var d []byte - var err error - if rawConfig == "" { - d, err = os.ReadFile(DefaultConfigFilename) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err) - } - } else { - d, err = base64.StdEncoding.DecodeString(rawConfig) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err) - } - } - err = toml.Unmarshal(d, &cfg) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrUnmarshalPerfConfig, err) - } - - log.Debug().Interface("Config", cfg).Msg("Parsed config") - return cfg, nil -} diff --git a/integration-tests/load/ocr/config.toml b/integration-tests/load/ocr/config.toml deleted file mode 100644 index df8364b3ee4..00000000000 --- a/integration-tests/load/ocr/config.toml +++ /dev/null @@ -1,20 +0,0 @@ -[Load] -test_duration = "3m" -rate_limit_unit_duration = "1m" -rate = 3 -verification_interval = "5s" -verification_timeout = "3m" -ea_change_interval = "5s" - -[Volume] -test_duration = "3m" -rate_limit_unit_duration = "1m" -vu_requests_per_unit = 10 -rate = 1 -verification_interval = "5s" -verification_timeout = "3m" - -ea_change_interval = "5s" - -[Common] -eth_funds = 3 \ No newline at end of file diff --git a/integration-tests/load/ocr/ocr_test.go b/integration-tests/load/ocr/ocr_test.go index 49e624ecd89..c6edf9122b9 100644 --- a/integration-tests/load/ocr/ocr_test.go +++ b/integration-tests/load/ocr/ocr_test.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/wasp" "github.com/smartcontractkit/chainlink-testing-framework/logging" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/k8s" ) @@ -27,21 +28,25 @@ func TestOCRLoad(t *testing.T) { require.NoError(t, err) ocrInstances, err := SetupFeed(cc, msClient, cd, bootstrapNode, workerNodes, lt) require.NoError(t, err) - cfg, err := ReadConfig() + + config, err := tc.GetConfig("Load", tc.OCR) require.NoError(t, err) - SimulateEAActivity(l, cfg.Load.EAChangeInterval.Duration(), ocrInstances, workerNodes, msClient) + + cfg := config.OCR + cfgl := config.Logging.Loki + SimulateEAActivity(l, cfg.Load.EAChangeInterval.Duration, ocrInstances, workerNodes, msClient) p := wasp.NewProfile() p.Add(wasp.NewGenerator(&wasp.Config{ T: t, GenName: "ocr", LoadType: wasp.RPS, - CallTimeout: cfg.Load.VerificationTimeout.Duration(), - RateLimitUnitDuration: cfg.Load.RateLimitUnitDuration.Duration(), - Schedule: wasp.Plain(cfg.Load.Rate, cfg.Load.TestDuration.Duration()), + CallTimeout: cfg.Load.VerificationTimeout.Duration, + RateLimitUnitDuration: cfg.Load.RateLimitUnitDuration.Duration, + Schedule: wasp.Plain(*cfg.Load.Rate, cfg.Load.TestDuration.Duration), Gun: NewGun(l, cc, ocrInstances), Labels: CommonTestLabels, - LokiConfig: wasp.NewEnvLokiConfig(), + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), })) _, err = p.Run(true) require.NoError(t, err) @@ -53,19 +58,22 @@ func TestOCRVolume(t *testing.T) { require.NoError(t, err) lt, err := SetupCluster(cc, cd, workerNodes) require.NoError(t, err) - cfg, err := ReadConfig() + config, err := tc.GetConfig("Volume", tc.OCR) require.NoError(t, err) + cfg := config.OCR + cfgl := config.Logging.Loki + p := wasp.NewProfile() p.Add(wasp.NewGenerator(&wasp.Config{ T: t, GenName: "ocr", LoadType: wasp.VU, - CallTimeout: cfg.Volume.VerificationTimeout.Duration(), - Schedule: wasp.Plain(cfg.Volume.Rate, cfg.Volume.TestDuration.Duration()), - VU: NewVU(l, cfg.Volume.VURequestsPerUnit, cfg.Volume.RateLimitUnitDuration.Duration(), cc, lt, cd, bootstrapNode, workerNodes, msClient), + CallTimeout: cfg.Volume.VerificationTimeout.Duration, + Schedule: wasp.Plain(*cfg.Volume.Rate, cfg.Volume.TestDuration.Duration), + VU: NewVU(l, *cfg.Volume.VURequestsPerUnit, cfg.Volume.RateLimitUnitDuration.Duration, cc, lt, cd, bootstrapNode, workerNodes, msClient), Labels: CommonTestLabels, - LokiConfig: wasp.NewEnvLokiConfig(), + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), })) _, err = p.Run(true) require.NoError(t, err) diff --git a/integration-tests/load/vrfv2/cmd/dashboard.go b/integration-tests/load/vrfv2/cmd/dashboard.go index 0fb7be2b78b..2536b4caed2 100644 --- a/integration-tests/load/vrfv2/cmd/dashboard.go +++ b/integration-tests/load/vrfv2/cmd/dashboard.go @@ -13,6 +13,7 @@ import ( ) func main() { + //TODO switch to TOML too? lokiDS := os.Getenv("DATA_SOURCE_NAME") d, err := wasp.NewDashboard(nil, []dashboard.Option{ diff --git a/integration-tests/load/vrfv2/config.go b/integration-tests/load/vrfv2/config.go deleted file mode 100644 index e97ac6a964e..00000000000 --- a/integration-tests/load/vrfv2/config.go +++ /dev/null @@ -1,151 +0,0 @@ -package loadvrfv2 - -import ( - "encoding/base64" - "fmt" - "os" - - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_config" - - "github.com/pelletier/go-toml/v2" - "github.com/rs/zerolog/log" - - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" -) - -const ( - DefaultConfigFilename = "config.toml" - SoakTestType = "Soak" - LoadTestType = "Load" - StressTestType = "Stress" - SpikeTestType = "Spike" - - ErrReadPerfConfig = "failed to read TOML config for performance tests" - ErrUnmarshalPerfConfig = "failed to unmarshal TOML config for performance tests" - ErrDeviationShouldBeLessThanOriginal = "`RandomnessRequestCountPerRequestDeviation` should be less than `RandomnessRequestCountPerRequest`" -) - -type PerformanceConfig struct { - Soak *Soak `toml:"Soak"` - Load *Load `toml:"Load"` - Stress *Stress `toml:"Stress"` - Spike *Spike `toml:"Spike"` - - Common *Common `toml:"Common"` - ExistingEnvConfig *ExistingEnvConfig `toml:"ExistingEnvConfig"` - NewEnvConfig *NewEnvConfig `toml:"NewEnvConfig"` -} - -type ExistingEnvConfig struct { - CoordinatorAddress string `toml:"coordinator_address"` - ConsumerAddress string `toml:"consumer_address"` - LinkAddress string `toml:"link_address"` - SubID uint64 `toml:"sub_id"` - KeyHash string `toml:"key_hash"` - Funding - CreateFundSubsAndAddConsumers bool `toml:"create_fund_subs_and_add_consumers"` - NodeSendingKeys []string `toml:"node_sending_keys"` -} - -type NewEnvConfig struct { - Funding -} - -type Common struct { - MinimumConfirmations uint16 `toml:"minimum_confirmations"` - CancelSubsAfterTestRun bool `toml:"cancel_subs_after_test_run"` -} - -type Funding struct { - SubFunding - NodeSendingKeyFunding float64 `toml:"node_sending_key_funding"` - NodeSendingKeyFundingMin float64 `toml:"node_sending_key_funding_min"` -} - -type SubFunding struct { - SubFundsLink float64 `toml:"sub_funds_link"` -} - -type Soak struct { - PerformanceTestConfig -} - -type Load struct { - PerformanceTestConfig -} - -type Stress struct { - PerformanceTestConfig -} - -type Spike struct { - PerformanceTestConfig -} - -type PerformanceTestConfig struct { - NumberOfSubToCreate int `toml:"number_of_sub_to_create"` - - RPS int64 `toml:"rps"` - //Duration *commonconfig.Duration `toml:"duration"` - RateLimitUnitDuration *commonconfig.Duration `toml:"rate_limit_unit_duration"` - RandomnessRequestCountPerRequest uint16 `toml:"randomness_request_count_per_request"` - RandomnessRequestCountPerRequestDeviation uint16 `toml:"randomness_request_count_per_request_deviation"` -} - -func ReadConfig() (*PerformanceConfig, error) { - var cfg *PerformanceConfig - rawConfig := os.Getenv("CONFIG") - var d []byte - var err error - if rawConfig == "" { - d, err = os.ReadFile(DefaultConfigFilename) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err) - } - } else { - d, err = base64.StdEncoding.DecodeString(rawConfig) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err) - } - } - err = toml.Unmarshal(d, &cfg) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrUnmarshalPerfConfig, err) - } - - if cfg.Soak.RandomnessRequestCountPerRequest <= cfg.Soak.RandomnessRequestCountPerRequestDeviation { - return nil, fmt.Errorf("%s, err: %w", ErrDeviationShouldBeLessThanOriginal, err) - } - - log.Debug().Interface("Config", cfg).Msg("Parsed config") - return cfg, nil -} - -func SetPerformanceTestConfig(testType string, vrfv2Config *vrfv2_config.VRFV2Config, cfg *PerformanceConfig) { - switch testType { - case SoakTestType: - vrfv2Config.NumberOfSubToCreate = cfg.Soak.NumberOfSubToCreate - vrfv2Config.RPS = cfg.Soak.RPS - vrfv2Config.RateLimitUnitDuration = cfg.Soak.RateLimitUnitDuration.Duration() - vrfv2Config.RandomnessRequestCountPerRequest = cfg.Soak.RandomnessRequestCountPerRequest - vrfv2Config.RandomnessRequestCountPerRequestDeviation = cfg.Soak.RandomnessRequestCountPerRequestDeviation - case LoadTestType: - vrfv2Config.NumberOfSubToCreate = cfg.Load.NumberOfSubToCreate - vrfv2Config.RPS = cfg.Load.RPS - vrfv2Config.RateLimitUnitDuration = cfg.Load.RateLimitUnitDuration.Duration() - vrfv2Config.RandomnessRequestCountPerRequest = cfg.Load.RandomnessRequestCountPerRequest - vrfv2Config.RandomnessRequestCountPerRequestDeviation = cfg.Load.RandomnessRequestCountPerRequestDeviation - case StressTestType: - vrfv2Config.NumberOfSubToCreate = cfg.Stress.NumberOfSubToCreate - vrfv2Config.RPS = cfg.Stress.RPS - vrfv2Config.RateLimitUnitDuration = cfg.Stress.RateLimitUnitDuration.Duration() - vrfv2Config.RandomnessRequestCountPerRequest = cfg.Stress.RandomnessRequestCountPerRequest - vrfv2Config.RandomnessRequestCountPerRequestDeviation = cfg.Stress.RandomnessRequestCountPerRequestDeviation - case SpikeTestType: - vrfv2Config.NumberOfSubToCreate = cfg.Spike.NumberOfSubToCreate - vrfv2Config.RPS = cfg.Spike.RPS - vrfv2Config.RateLimitUnitDuration = cfg.Spike.RateLimitUnitDuration.Duration() - vrfv2Config.RandomnessRequestCountPerRequest = cfg.Spike.RandomnessRequestCountPerRequest - vrfv2Config.RandomnessRequestCountPerRequestDeviation = cfg.Spike.RandomnessRequestCountPerRequestDeviation - } -} diff --git a/integration-tests/load/vrfv2/config.toml b/integration-tests/load/vrfv2/config.toml deleted file mode 100644 index 6f54d1ec998..00000000000 --- a/integration-tests/load/vrfv2/config.toml +++ /dev/null @@ -1,58 +0,0 @@ - -[Common] -minimum_confirmations = 3 -cancel_subs_after_test_run = true - -[NewEnvConfig] -sub_funds_link = 1000 -node_sending_key_funding = 1000 - -[ExistingEnvConfig] -coordinator_address = "" -consumer_address = "" -sub_id = 1 -key_hash = "" -create_fund_subs_and_add_consumers = true -link_address = "" -sub_funds_link = 10 -node_sending_key_funding_min = 1 -node_sending_keys = [ - "", - "", - "", - "", - "", - "", -] - -# 10 RPM - 1 tx request with 1 rand request in each tx every 6 seconds -[Soak] -rate_limit_unit_duration = "6s" -rps = 1 -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 - -# approx 60 RPM - 1 tx request with 3 rand requests in each tx every 3 seconds -[Load] -rate_limit_unit_duration = "3s" -rps = 1 -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 - -# approx 540 RPM - 3 tx requests per second with 4 rand requests in each tx -[Stress] -rate_limit_unit_duration = "1s" -rps = 3 -randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 - -# approx 150 RPM - 1 tx request with 150 rand requests in each tx every 60 seconds -[Spike] -rate_limit_unit_duration = "1m" -rps = 1 -randomness_request_count_per_request = 150 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 diff --git a/integration-tests/load/vrfv2/gun.go b/integration-tests/load/vrfv2/gun.go index fd8cb6195e8..bd1dc96fadf 100644 --- a/integration-tests/load/vrfv2/gun.go +++ b/integration-tests/load/vrfv2/gun.go @@ -4,36 +4,35 @@ import ( "math/rand" "github.com/rs/zerolog" - "github.com/smartcontractkit/wasp" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_config" + "github.com/smartcontractkit/chainlink/integration-tests/types" ) /* SingleHashGun is a gun that constantly requests randomness for one feed */ type SingleHashGun struct { - contracts *vrfv2_actions.VRFV2Contracts - keyHash [32]byte - subIDs []uint64 - vrfv2Config vrfv2_config.VRFV2Config - logger zerolog.Logger + contracts *vrfv2_actions.VRFV2Contracts + keyHash [32]byte + subIDs []uint64 + testConfig types.VRFv2TestConfig + logger zerolog.Logger } func NewSingleHashGun( contracts *vrfv2_actions.VRFV2Contracts, keyHash [32]byte, subIDs []uint64, - vrfv2Config vrfv2_config.VRFV2Config, + testConfig types.VRFv2TestConfig, logger zerolog.Logger, ) *SingleHashGun { return &SingleHashGun{ - contracts: contracts, - keyHash: keyHash, - subIDs: subIDs, - vrfv2Config: vrfv2Config, - logger: logger, + contracts: contracts, + keyHash: keyHash, + subIDs: subIDs, + testConfig: testConfig, + logger: logger, } } @@ -41,19 +40,23 @@ func NewSingleHashGun( func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { //todo - should work with multiple consumers and consumers having different keyhashes and wallets + vrfv2Config := m.testConfig.GetVRFv2Config().General //randomly increase/decrease randomness request count per TX - randomnessRequestCountPerRequest := deviateValue(m.vrfv2Config.RandomnessRequestCountPerRequest, m.vrfv2Config.RandomnessRequestCountPerRequestDeviation) + randomnessRequestCountPerRequest := deviateValue(*vrfv2Config.RandomnessRequestCountPerRequest, *vrfv2Config.RandomnessRequestCountPerRequestDeviation) _, err := vrfv2_actions.RequestRandomnessAndWaitForFulfillment( + m.logger, //the same consumer is used for all requests and in all subs m.contracts.LoadTestConsumers[0], m.contracts.Coordinator, - &vrfv2_actions.VRFV2Data{VRFV2KeyData: vrfv2_actions.VRFV2KeyData{KeyHash: m.keyHash}}, //randomly pick a subID from pool of subIDs m.subIDs[randInRange(0, len(m.subIDs)-1)], + &vrfv2_actions.VRFV2Data{VRFV2KeyData: vrfv2_actions.VRFV2KeyData{KeyHash: m.keyHash}}, + *vrfv2Config.MinimumConfirmations, + *vrfv2Config.CallbackGasLimit, + *vrfv2Config.NumberOfWords, randomnessRequestCountPerRequest, - m.vrfv2Config, - m.vrfv2Config.RandomWordsFulfilledEventTimeout, - m.logger, + *vrfv2Config.RandomnessRequestCountPerRequestDeviation, + vrfv2Config.RandomWordsFulfilledEventTimeout.Duration, ) if err != nil { return &wasp.Response{Error: err.Error(), Failed: true} diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index b31f02ab46f..142764b1719 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -3,13 +3,11 @@ package loadvrfv2 import ( "context" "math/big" - "os" "sync" "testing" "time" "github.com/ethereum/go-ethereum/common" - "github.com/kelseyhightower/envconfig" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" @@ -18,7 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_config" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" @@ -26,6 +24,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) var ( @@ -39,26 +38,21 @@ var ( "branch": "vrfv2_healthcheck", "commit": "vrfv2_healthcheck", } - - testType = os.Getenv("TEST_TYPE") ) func TestVRFV2Performance(t *testing.T) { - cfg, err := ReadConfig() + l := logging.GetTestLogger(t) + + testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err) - var vrfv2Config vrfv2_config.VRFV2Config - err = envconfig.Process("VRFV2", &vrfv2Config) + testConfig, err := tc.GetConfig(testType, tc.VRFv2) require.NoError(t, err) testReporter := &testreporters.VRFV2TestReporter{} + vrfv2Config := testConfig.VRFv2 - SetPerformanceTestConfig(testType, &vrfv2Config, cfg) - - l := logging.GetTestLogger(t) - //todo: temporary solution with envconfig and toml config until VRF-662 is implemented - vrfv2Config.MinimumConfirmations = cfg.Common.MinimumConfirmations - - lokiConfig := wasp.NewEnvLokiConfig() + cfgl := testConfig.Logging.Loki + lokiConfig := wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken) lc, err := wasp.NewLokiClient(lokiConfig) if err != nil { l.Error().Err(err).Msg(ErrLokiClient) @@ -68,35 +62,38 @@ func TestVRFV2Performance(t *testing.T) { updatedLabels := UpdateLabels(labels, t) l.Info(). - Str("Test Type", testType). - Str("Test Duration", vrfv2Config.TestDuration.Truncate(time.Second).String()). - Int64("RPS", vrfv2Config.RPS). - Str("RateLimitUnitDuration", vrfv2Config.RateLimitUnitDuration.String()). - Uint16("RandomnessRequestCountPerRequest", vrfv2Config.RandomnessRequestCountPerRequest). - Uint16("RandomnessRequestCountPerRequestDeviation", vrfv2Config.RandomnessRequestCountPerRequestDeviation). - Bool("UseExistingEnv", vrfv2Config.UseExistingEnv). + Str("Test Type", string(testType)). + Str("Test Duration", vrfv2Config.Performance.TestDuration.Duration.Truncate(time.Second).String()). + Int64("RPS", *vrfv2Config.Performance.RPS). + Str("RateLimitUnitDuration", vrfv2Config.Performance.RateLimitUnitDuration.String()). + Uint16("RandomnessRequestCountPerRequest", *vrfv2Config.General.RandomnessRequestCountPerRequest). + Uint16("RandomnessRequestCountPerRequestDeviation", *vrfv2Config.General.RandomnessRequestCountPerRequestDeviation). + Bool("UseExistingEnv", *vrfv2Config.Performance.UseExistingEnv). Msg("Performance Test Configuration") - if vrfv2Config.UseExistingEnv { + if *vrfv2Config.Performance.UseExistingEnv { //todo: temporary solution with envconfig and toml config until VRF-662 is implemented - vrfv2Config.CoordinatorAddress = cfg.ExistingEnvConfig.CoordinatorAddress - vrfv2Config.ConsumerAddress = cfg.ExistingEnvConfig.ConsumerAddress - vrfv2Config.LinkAddress = cfg.ExistingEnvConfig.LinkAddress - vrfv2Config.SubscriptionFundingAmountLink = cfg.ExistingEnvConfig.SubFunding.SubFundsLink - vrfv2Config.SubID = cfg.ExistingEnvConfig.SubID - vrfv2Config.KeyHash = cfg.ExistingEnvConfig.KeyHash + cfg := testConfig.VRFv2 + + vrfv2Config.Performance.CoordinatorAddress = cfg.ExistingEnvConfig.CoordinatorAddress + vrfv2Config.Performance.ConsumerAddress = cfg.ExistingEnvConfig.ConsumerAddress + vrfv2Config.Performance.LinkAddress = cfg.ExistingEnvConfig.LinkAddress + vrfv2Config.General.SubscriptionFundingAmountLink = cfg.ExistingEnvConfig.SubFunding.SubFundsLink + vrfv2Config.Performance.SubID = cfg.ExistingEnvConfig.SubID + vrfv2Config.Performance.KeyHash = cfg.ExistingEnvConfig.KeyHash env, err = test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&testConfig). WithCustomCleanup( func() { - teardown(t, vrfv2Contracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, testType, vrfv2Config) + teardown(t, vrfv2Contracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, string(testType), &testConfig) if env.EVMClient.NetworkSimulated() { l.Info(). Str("Network Name", env.EVMClient.GetNetworkName()). Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") } else { - if cfg.Common.CancelSubsAfterTestRun { + if *vrfv2Config.Common.CancelSubsAfterTestRun { //cancel subs and return funds to sub owner cancelSubsAndReturnFunds(subIDs, l) } @@ -106,38 +103,38 @@ func TestVRFV2Performance(t *testing.T) { require.NoError(t, err, "error creating test env") - coordinator, err := env.ContractLoader.LoadVRFCoordinatorV2(vrfv2Config.CoordinatorAddress) + coordinator, err := env.ContractLoader.LoadVRFCoordinatorV2(*vrfv2Config.Performance.CoordinatorAddress) require.NoError(t, err) var consumers []contracts.VRFv2LoadTestConsumer - if cfg.ExistingEnvConfig.CreateFundSubsAndAddConsumers { - linkToken, err := env.ContractLoader.LoadLINKToken(vrfv2Config.LinkAddress) + if *cfg.ExistingEnvConfig.CreateFundSubsAndAddConsumers { + linkToken, err := env.ContractLoader.LoadLINKToken(*vrfv2Config.Performance.LinkAddress) require.NoError(t, err) consumers, err = vrfv2_actions.DeployVRFV2Consumers(env.ContractDeployer, coordinator.Address(), 1) require.NoError(t, err) err = env.EVMClient.WaitForEvents() require.NoError(t, err, vrfv2_actions.ErrWaitTXsComplete) l.Info(). - Str("Coordinator", cfg.ExistingEnvConfig.CoordinatorAddress). - Int("Number of Subs to create", vrfv2Config.NumberOfSubToCreate). + Str("Coordinator", *cfg.ExistingEnvConfig.CoordinatorAddress). + Int("Number of Subs to create", *vrfv2Config.General.NumberOfSubToCreate). Msg("Creating and funding subscriptions, deploying and adding consumers to subs") subIDs, err = vrfv2_actions.CreateFundSubsAndAddConsumers( env, - vrfv2Config, + big.NewFloat(*cfg.General.SubscriptionFundingAmountLink), linkToken, coordinator, consumers, - vrfv2Config.NumberOfSubToCreate, + *vrfv2Config.General.NumberOfSubToCreate, ) require.NoError(t, err) } else { - consumer, err := env.ContractLoader.LoadVRFv2LoadTestConsumer(vrfv2Config.ConsumerAddress) + consumer, err := env.ContractLoader.LoadVRFv2LoadTestConsumer(*vrfv2Config.Performance.ConsumerAddress) require.NoError(t, err) consumers = append(consumers, consumer) - subIDs = append(subIDs, vrfv2Config.SubID) + subIDs = append(subIDs, *vrfv2Config.Performance.SubID) } - err = FundNodesIfNeeded(cfg, env.EVMClient, l) + err = FundNodesIfNeeded(&testConfig, env.EVMClient, l) require.NoError(t, err) vrfv2Contracts = &vrfv2_actions.VRFV2Contracts{ @@ -150,7 +147,7 @@ func TestVRFV2Performance(t *testing.T) { VRFV2KeyData: vrfv2_actions.VRFV2KeyData{ VRFKey: nil, EncodedProvingKey: [2]*big.Int{}, - KeyHash: common.HexToHash(vrfv2Config.KeyHash), + KeyHash: common.HexToHash(*vrfv2Config.Performance.KeyHash), }, VRFJob: nil, PrimaryEthAddress: "", @@ -159,26 +156,27 @@ func TestVRFV2Performance(t *testing.T) { } else { //todo: temporary solution with envconfig and toml config until VRF-662 is implemented - vrfv2Config.ChainlinkNodeFunding = cfg.NewEnvConfig.NodeSendingKeyFunding - vrfv2Config.SubscriptionFundingAmountLink = cfg.NewEnvConfig.Funding.SubFundsLink + testConfig.Common.ChainlinkNodeFunding = testConfig.VRFv2.NewEnvConfig.NodeSendingKeyFunding + vrfv2Config.General.SubscriptionFundingAmountLink = testConfig.VRFv2.NewEnvConfig.Funding.SubFundsLink - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + network, err := actions.EthereumNetworkConfigFromConfig(l, &testConfig) require.NoError(t, err, "Error building ethereum network config") env, err = test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&testConfig). WithPrivateEthereumNetwork(network). WithCLNodes(1). - WithFunding(big.NewFloat(vrfv2Config.ChainlinkNodeFunding)). + WithFunding(big.NewFloat(*testConfig.Common.ChainlinkNodeFunding)). WithCustomCleanup( func() { - teardown(t, vrfv2Contracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, testType, vrfv2Config) + teardown(t, vrfv2Contracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, string(testType), &testConfig) if env.EVMClient.NetworkSimulated() { l.Info(). Str("Network Name", env.EVMClient.GetNetworkName()). Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") } else { - if cfg.Common.CancelSubsAfterTestRun { + if *testConfig.VRFv2.Common.CancelSubsAfterTestRun { //cancel subs and return funds to sub owner cancelSubsAndReturnFunds(subIDs, l) } @@ -193,7 +191,7 @@ func TestVRFV2Performance(t *testing.T) { env.ParallelTransactions(true) - mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(vrfv2Config.LinkNativeFeedResponse)) + mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(*vrfv2Config.General.LinkNativeFeedResponse)) require.NoError(t, err, "error deploying mock ETH/LINK feed") linkToken, err := actions.DeployLINKToken(env.ContractDeployer) @@ -204,7 +202,7 @@ func TestVRFV2Performance(t *testing.T) { vrfv2Contracts, subIDs, vrfv2Data, err = vrfv2_actions.SetupVRFV2Environment( env, - vrfv2Config, + &testConfig, useVRFOwner, useTestCoordinator, linkToken, @@ -213,7 +211,7 @@ func TestVRFV2Performance(t *testing.T) { env.EVMClient.GetDefaultWallet().Address(), 0, 1, - vrfv2Config.NumberOfSubToCreate, + *vrfv2Config.General.NumberOfSubToCreate, l, ) require.NoError(t, err, "error setting up VRF v2 env") @@ -231,12 +229,12 @@ func TestVRFV2Performance(t *testing.T) { T: t, LoadType: wasp.RPS, GenName: "gun", - RateLimitUnitDuration: vrfv2Config.RateLimitUnitDuration, + RateLimitUnitDuration: vrfv2Config.Performance.RateLimitUnitDuration.Duration, Gun: NewSingleHashGun( vrfv2Contracts, vrfv2Data.KeyHash, subIDs, - vrfv2Config, + &testConfig, l, ), Labels: labels, @@ -253,8 +251,8 @@ func TestVRFV2Performance(t *testing.T) { t.Run("vrfv2 performance test", func(t *testing.T) { singleFeedConfig.Schedule = wasp.Plain( - vrfv2Config.RPS, - vrfv2Config.TestDuration, + *vrfv2Config.Performance.RPS, + vrfv2Config.Performance.TestDuration.Duration, ) _, err = wasp.NewProfile(). Add(wasp.NewGenerator(singleFeedConfig)). @@ -297,15 +295,16 @@ func cancelSubsAndReturnFunds(subIDs []uint64, l zerolog.Logger) { } } -func FundNodesIfNeeded(cfg *PerformanceConfig, client blockchain.EVMClient, l zerolog.Logger) error { - if cfg.ExistingEnvConfig.NodeSendingKeyFundingMin > 0 { +func FundNodesIfNeeded(vrfv2TestConfig tc.VRFv2TestConfig, client blockchain.EVMClient, l zerolog.Logger) error { + cfg := vrfv2TestConfig.GetVRFv2Config() + if cfg.ExistingEnvConfig.NodeSendingKeyFundingMin != nil && *cfg.ExistingEnvConfig.NodeSendingKeyFundingMin > 0 { for _, sendingKey := range cfg.ExistingEnvConfig.NodeSendingKeys { address := common.HexToAddress(sendingKey) sendingKeyBalance, err := client.BalanceAt(context.Background(), address) if err != nil { return err } - fundingAtLeast := conversions.EtherToWei(big.NewFloat(cfg.ExistingEnvConfig.NodeSendingKeyFundingMin)) + fundingAtLeast := conversions.EtherToWei(big.NewFloat(*cfg.ExistingEnvConfig.NodeSendingKeyFundingMin)) fundingToSendWei := new(big.Int).Sub(fundingAtLeast, sendingKeyBalance) fundingToSendEth := conversions.WeiToEther(fundingToSendWei) if fundingToSendWei.Cmp(big.NewInt(0)) == 1 { @@ -338,7 +337,7 @@ func teardown( updatedLabels map[string]string, testReporter *testreporters.VRFV2TestReporter, testType string, - vrfv2Config vrfv2_config.VRFV2Config, + testConfig *tc.TestConfig, ) { //send final results to Loki metrics := GetLoadTestMetrics(consumer) @@ -351,7 +350,7 @@ func teardown( metrics.AverageFulfillmentInMillions, metrics.SlowestFulfillment, metrics.FastestFulfillment, - vrfv2Config, + testConfig, ) // send Slack notification diff --git a/integration-tests/load/vrfv2plus/cmd/dashboard.go b/integration-tests/load/vrfv2plus/cmd/dashboard.go index 049ee9ff2e9..2be0e265041 100644 --- a/integration-tests/load/vrfv2plus/cmd/dashboard.go +++ b/integration-tests/load/vrfv2plus/cmd/dashboard.go @@ -13,6 +13,7 @@ import ( ) func main() { + //TODO switch to TOML too? lokiDS := os.Getenv("DATA_SOURCE_NAME") d, err := wasp.NewDashboard(nil, []dashboard.Option{ diff --git a/integration-tests/load/vrfv2plus/config.go b/integration-tests/load/vrfv2plus/config.go deleted file mode 100644 index 25f295a4039..00000000000 --- a/integration-tests/load/vrfv2plus/config.go +++ /dev/null @@ -1,152 +0,0 @@ -package loadvrfv2plus - -import ( - "encoding/base64" - "fmt" - "os" - - "github.com/pelletier/go-toml/v2" - "github.com/rs/zerolog/log" - - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config" -) - -const ( - DefaultConfigFilename = "config.toml" - SoakTestType = "Soak" - LoadTestType = "Load" - StressTestType = "Stress" - SpikeTestType = "Spike" - - ErrReadPerfConfig = "failed to read TOML config for performance tests" - ErrUnmarshalPerfConfig = "failed to unmarshal TOML config for performance tests" - ErrDeviationShouldBeLessThanOriginal = "`RandomnessRequestCountPerRequestDeviation` should be less than `RandomnessRequestCountPerRequest`" -) - -type PerformanceConfig struct { - Soak *Soak `toml:"Soak"` - Load *Load `toml:"Load"` - Stress *Stress `toml:"Stress"` - Spike *Spike `toml:"Spike"` - - Common *Common `toml:"Common"` - ExistingEnvConfig *ExistingEnvConfig `toml:"ExistingEnvConfig"` - NewEnvConfig *NewEnvConfig `toml:"NewEnvConfig"` -} - -type ExistingEnvConfig struct { - CoordinatorAddress string `toml:"coordinator_address"` - ConsumerAddress string `toml:"consumer_address"` - LinkAddress string `toml:"link_address"` - SubID string `toml:"sub_id"` - KeyHash string `toml:"key_hash"` - Funding - CreateFundSubsAndAddConsumers bool `toml:"create_fund_subs_and_add_consumers"` - NodeSendingKeys []string `toml:"node_sending_keys"` -} - -type NewEnvConfig struct { - Funding -} - -type Common struct { - MinimumConfirmations uint16 `toml:"minimum_confirmations"` - CancelSubsAfterTestRun bool `toml:"cancel_subs_after_test_run"` - SubBillingType string `toml:"sub_billing_type"` -} - -type Funding struct { - SubFunding - NodeSendingKeyFunding float64 `toml:"node_sending_key_funding"` - NodeSendingKeyFundingMin float64 `toml:"node_sending_key_funding_min"` -} - -type SubFunding struct { - SubFundsLink float64 `toml:"sub_funds_link"` - SubFundsNative float64 `toml:"sub_funds_native"` -} - -type Soak struct { - PerformanceTestConfig -} - -type Load struct { - PerformanceTestConfig -} - -type Stress struct { - PerformanceTestConfig -} - -type Spike struct { - PerformanceTestConfig -} - -type PerformanceTestConfig struct { - NumberOfSubToCreate int `toml:"number_of_sub_to_create"` - - RPS int64 `toml:"rps"` - //Duration *commonconfig.Duration `toml:"duration"` - RateLimitUnitDuration *commonconfig.Duration `toml:"rate_limit_unit_duration"` - RandomnessRequestCountPerRequest uint16 `toml:"randomness_request_count_per_request"` - RandomnessRequestCountPerRequestDeviation uint16 `toml:"randomness_request_count_per_request_deviation"` -} - -func ReadConfig() (*PerformanceConfig, error) { - var cfg *PerformanceConfig - rawConfig := os.Getenv("CONFIG") - var d []byte - var err error - if rawConfig == "" { - d, err = os.ReadFile(DefaultConfigFilename) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err) - } - } else { - d, err = base64.StdEncoding.DecodeString(rawConfig) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrReadPerfConfig, err) - } - } - err = toml.Unmarshal(d, &cfg) - if err != nil { - return nil, fmt.Errorf("%s, err: %w", ErrUnmarshalPerfConfig, err) - } - - if cfg.Soak.RandomnessRequestCountPerRequest <= cfg.Soak.RandomnessRequestCountPerRequestDeviation { - return nil, fmt.Errorf("%s, err: %w", ErrDeviationShouldBeLessThanOriginal, err) - } - - log.Debug().Interface("Config", cfg).Msg("Parsed config") - return cfg, nil -} - -func SetPerformanceTestConfig(testType string, vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig, cfg *PerformanceConfig) { - switch testType { - case SoakTestType: - vrfv2PlusConfig.NumberOfSubToCreate = cfg.Soak.NumberOfSubToCreate - vrfv2PlusConfig.RPS = cfg.Soak.RPS - vrfv2PlusConfig.RateLimitUnitDuration = cfg.Soak.RateLimitUnitDuration.Duration() - vrfv2PlusConfig.RandomnessRequestCountPerRequest = cfg.Soak.RandomnessRequestCountPerRequest - vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation = cfg.Soak.RandomnessRequestCountPerRequestDeviation - case LoadTestType: - vrfv2PlusConfig.NumberOfSubToCreate = cfg.Load.NumberOfSubToCreate - vrfv2PlusConfig.RPS = cfg.Load.RPS - vrfv2PlusConfig.RateLimitUnitDuration = cfg.Load.RateLimitUnitDuration.Duration() - vrfv2PlusConfig.RandomnessRequestCountPerRequest = cfg.Load.RandomnessRequestCountPerRequest - vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation = cfg.Load.RandomnessRequestCountPerRequestDeviation - case StressTestType: - vrfv2PlusConfig.NumberOfSubToCreate = cfg.Stress.NumberOfSubToCreate - vrfv2PlusConfig.RPS = cfg.Stress.RPS - vrfv2PlusConfig.RateLimitUnitDuration = cfg.Stress.RateLimitUnitDuration.Duration() - vrfv2PlusConfig.RandomnessRequestCountPerRequest = cfg.Stress.RandomnessRequestCountPerRequest - vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation = cfg.Stress.RandomnessRequestCountPerRequestDeviation - case SpikeTestType: - vrfv2PlusConfig.NumberOfSubToCreate = cfg.Spike.NumberOfSubToCreate - vrfv2PlusConfig.RPS = cfg.Spike.RPS - vrfv2PlusConfig.RateLimitUnitDuration = cfg.Spike.RateLimitUnitDuration.Duration() - vrfv2PlusConfig.RandomnessRequestCountPerRequest = cfg.Spike.RandomnessRequestCountPerRequest - vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation = cfg.Spike.RandomnessRequestCountPerRequestDeviation - } -} diff --git a/integration-tests/load/vrfv2plus/config.toml b/integration-tests/load/vrfv2plus/config.toml deleted file mode 100644 index 9572fb9c45f..00000000000 --- a/integration-tests/load/vrfv2plus/config.toml +++ /dev/null @@ -1,57 +0,0 @@ -[Common] -minimum_confirmations = 1 -cancel_subs_after_test_run = true -sub_billing_type = "LINK_AND_NATIVE" # LINK_AND_NATIVE, LINK, NATIVE - -[NewEnvConfig] -sub_funds_link = 1 -sub_funds_native = 1 -node_funds = 10 -node_sending_key_funding = 1000 - -[ExistingEnvConfig] -coordinator_address = "" -consumer_address = "" -sub_id = "" -key_hash = "" -create_fund_subs_and_add_consumers = true -node_sending_key_funding_min = 10 -node_sending_keys = [ - "", - "" -] -sub_funds_native = 10 -link_address = "" -sub_funds_link = 10 - -# 10 RPM - 1 tx request with 1 rand request in each tx every 6 seconds -[Soak] -rate_limit_unit_duration = "6s" -rps = 1 -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 - -# approx 60 RPM - 1 tx request with 3 rand requests in each tx every 3 seconds -[Load] -rate_limit_unit_duration = "1s" -rps = 1 -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 - -# approx 540 RPM - 3 tx requests per second with 4 rand requests in each tx -[Stress] -rate_limit_unit_duration = "1s" -rps = 3 -randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 - -# approx 150 RPM - 1 tx request with 150 rand requests in each tx every 60 seconds -[Spike] -rate_limit_unit_duration = "1m" -rps = 1 -randomness_request_count_per_request = 150 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go index 03603e7bb05..bfa56d5f3dc 100644 --- a/integration-tests/load/vrfv2plus/gun.go +++ b/integration-tests/load/vrfv2plus/gun.go @@ -9,32 +9,33 @@ import ( "github.com/smartcontractkit/wasp" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config" + vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" + "github.com/smartcontractkit/chainlink/integration-tests/types" ) /* SingleHashGun is a gun that constantly requests randomness for one feed */ type SingleHashGun struct { - contracts *vrfv2plus.VRFV2_5Contracts - keyHash [32]byte - subIDs []*big.Int - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig - logger zerolog.Logger + contracts *vrfv2plus.VRFV2_5Contracts + keyHash [32]byte + subIDs []*big.Int + testConfig types.VRFv2PlusTestConfig + logger zerolog.Logger } func NewSingleHashGun( contracts *vrfv2plus.VRFV2_5Contracts, keyHash [32]byte, subIDs []*big.Int, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + testConfig types.VRFv2PlusTestConfig, logger zerolog.Logger, ) *SingleHashGun { return &SingleHashGun{ - contracts: contracts, - keyHash: keyHash, - subIDs: subIDs, - vrfv2PlusConfig: vrfv2PlusConfig, - logger: logger, + contracts: contracts, + keyHash: keyHash, + subIDs: subIDs, + testConfig: testConfig, + logger: logger, } } @@ -42,13 +43,13 @@ func NewSingleHashGun( func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { //todo - should work with multiple consumers and consumers having different keyhashes and wallets - billingType, err := selectBillingType(m.vrfv2PlusConfig.SubscriptionBillingType) + billingType, err := selectBillingType(*m.testConfig.GetVRFv2PlusConfig().General.SubscriptionBillingType) if err != nil { return &wasp.Response{Error: err.Error(), Failed: true} } //randomly increase/decrease randomness request count per TX - randomnessRequestCountPerRequest := deviateValue(m.vrfv2PlusConfig.RandomnessRequestCountPerRequest, m.vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation) + randomnessRequestCountPerRequest := deviateValue(*m.testConfig.GetVRFv2PlusConfig().General.RandomnessRequestCountPerRequest, *m.testConfig.GetVRFv2PlusConfig().General.RandomnessRequestCountPerRequestDeviation) _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( //the same consumer is used for all requests and in all subs m.contracts.LoadTestConsumers[0], @@ -58,9 +59,12 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { m.subIDs[randInRange(0, len(m.subIDs)-1)], //randomly pick payment type billingType, + *m.testConfig.GetVRFv2PlusConfig().General.MinimumConfirmations, + *m.testConfig.GetVRFv2PlusConfig().General.CallbackGasLimit, + *m.testConfig.GetVRFv2PlusConfig().General.NumberOfWords, randomnessRequestCountPerRequest, - m.vrfv2PlusConfig, - m.vrfv2PlusConfig.RandomWordsFulfilledEventTimeout, + *m.testConfig.GetVRFv2PlusConfig().General.RandomnessRequestCountPerRequestDeviation, + m.testConfig.GetVRFv2PlusConfig().General.RandomWordsFulfilledEventTimeout.Duration, m.logger, ) if err != nil { @@ -86,12 +90,12 @@ func randInRange(min int, max int) int { } func selectBillingType(billingType string) (bool, error) { - switch billingType { - case vrfv2plus_config.BILLING_TYPE_LINK: + switch vrfv2plus_config.BillingType(billingType) { + case vrfv2plus_config.BillingType_Link: return false, nil - case vrfv2plus_config.BILLING_TYPE_NATIVE: + case vrfv2plus_config.BillingType_Native: return true, nil - case vrfv2plus_config.BILLING_TYPE_LINK_AND_NATIVE: + case vrfv2plus_config.BillingType_Link_and_Native: return randBool(), nil default: return false, fmt.Errorf("invalid billing type: %s", billingType) diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index cb68386d117..b32d40e983e 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -3,13 +3,11 @@ package loadvrfv2plus import ( "context" "math/big" - "os" "sync" "testing" "time" "github.com/ethereum/go-ethereum/common" - "github.com/kelseyhightower/envconfig" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" @@ -23,9 +21,11 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" ) var ( @@ -39,28 +39,21 @@ var ( "branch": "vrfv2Plus_healthcheck", "commit": "vrfv2Plus_healthcheck", } - - testType = os.Getenv("TEST_TYPE") ) func TestVRFV2PlusPerformance(t *testing.T) { - cfg, err := ReadConfig() + l := logging.GetTestLogger(t) + + testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err) - var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig - err = envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) + testConfig, err := tc.GetConfig(testType, tc.VRFv2Plus) require.NoError(t, err) + cfgl := testConfig.Logging.Loki + vrfv2PlusConfig := testConfig.VRFv2Plus testReporter := &testreporters.VRFV2PlusTestReporter{} - SetPerformanceTestConfig(testType, &vrfv2PlusConfig, cfg) - - l := logging.GetTestLogger(t) - //todo: temporary solution with envconfig and toml config until VRF-662 is implemented - vrfv2PlusConfig.MinimumConfirmations = cfg.Common.MinimumConfirmations - vrfv2PlusConfig.SubscriptionBillingType = cfg.Common.SubBillingType - - lokiConfig := wasp.NewEnvLokiConfig() - lc, err := wasp.NewLokiClient(lokiConfig) + lc, err := wasp.NewLokiClient(wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken)) if err != nil { l.Error().Err(err).Msg(ErrLokiClient) return @@ -69,36 +62,37 @@ func TestVRFV2PlusPerformance(t *testing.T) { updatedLabels := UpdateLabels(labels, t) l.Info(). - Str("Test Type", testType). - Str("Test Duration", vrfv2PlusConfig.TestDuration.Truncate(time.Second).String()). - Int64("RPS", vrfv2PlusConfig.RPS). - Str("RateLimitUnitDuration", vrfv2PlusConfig.RateLimitUnitDuration.String()). - Uint16("RandomnessRequestCountPerRequest", vrfv2PlusConfig.RandomnessRequestCountPerRequest). - Uint16("RandomnessRequestCountPerRequestDeviation", vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation). - Bool("UseExistingEnv", vrfv2PlusConfig.UseExistingEnv). + Str("Test Type", string(testType)). + Str("Test Duration", vrfv2PlusConfig.Performance.TestDuration.Duration.Truncate(time.Second).String()). + Int64("RPS", *vrfv2PlusConfig.Performance.RPS). + Str("RateLimitUnitDuration", vrfv2PlusConfig.Performance.RateLimitUnitDuration.String()). + Uint16("RandomnessRequestCountPerRequest", *vrfv2PlusConfig.General.RandomnessRequestCountPerRequest). + Uint16("RandomnessRequestCountPerRequestDeviation", *vrfv2PlusConfig.General.RandomnessRequestCountPerRequestDeviation). + Bool("UseExistingEnv", *vrfv2PlusConfig.Performance.UseExistingEnv). Msg("Performance Test Configuration") - if vrfv2PlusConfig.UseExistingEnv { + if *vrfv2PlusConfig.Performance.UseExistingEnv { //todo: temporary solution with envconfig and toml config until VRF-662 is implemented - vrfv2PlusConfig.CoordinatorAddress = cfg.ExistingEnvConfig.CoordinatorAddress - vrfv2PlusConfig.ConsumerAddress = cfg.ExistingEnvConfig.ConsumerAddress - vrfv2PlusConfig.LinkAddress = cfg.ExistingEnvConfig.LinkAddress - vrfv2PlusConfig.SubscriptionFundingAmountLink = cfg.ExistingEnvConfig.SubFunding.SubFundsLink - vrfv2PlusConfig.SubscriptionFundingAmountNative = cfg.ExistingEnvConfig.SubFunding.SubFundsNative - vrfv2PlusConfig.SubID = cfg.ExistingEnvConfig.SubID - vrfv2PlusConfig.KeyHash = cfg.ExistingEnvConfig.KeyHash + vrfv2PlusConfig.Performance.CoordinatorAddress = testConfig.VRFv2Plus.ExistingEnvConfig.CoordinatorAddress + vrfv2PlusConfig.Performance.ConsumerAddress = testConfig.VRFv2Plus.ExistingEnvConfig.ConsumerAddress + vrfv2PlusConfig.Performance.LinkAddress = testConfig.VRFv2Plus.ExistingEnvConfig.LinkAddress + vrfv2PlusConfig.General.SubscriptionFundingAmountLink = testConfig.VRFv2Plus.ExistingEnvConfig.SubFunding.SubFundsLink + vrfv2PlusConfig.General.SubscriptionFundingAmountNative = testConfig.VRFv2Plus.ExistingEnvConfig.SubFunding.SubFundsNative + vrfv2PlusConfig.Performance.SubID = testConfig.VRFv2Plus.ExistingEnvConfig.SubID + vrfv2PlusConfig.Performance.KeyHash = testConfig.VRFv2Plus.ExistingEnvConfig.KeyHash env, err = test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&testConfig). WithCustomCleanup( func() { - teardown(t, vrfv2PlusContracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, testType, vrfv2PlusConfig) + teardown(t, vrfv2PlusContracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, string(testType), &testConfig) if env.EVMClient.NetworkSimulated() { l.Info(). Str("Network Name", env.EVMClient.GetNetworkName()). Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") } else { - if cfg.Common.CancelSubsAfterTestRun { + if *testConfig.VRFv2Plus.Common.CancelSubsAfterTestRun { //cancel subs and return funds to sub owner cancelSubsAndReturnFunds(subIDs, l) } @@ -108,41 +102,43 @@ func TestVRFV2PlusPerformance(t *testing.T) { require.NoError(t, err, "error creating test env") - coordinator, err := env.ContractLoader.LoadVRFCoordinatorV2_5(vrfv2PlusConfig.CoordinatorAddress) + coordinator, err := env.ContractLoader.LoadVRFCoordinatorV2_5(*vrfv2PlusConfig.Performance.CoordinatorAddress) require.NoError(t, err) var consumers []contracts.VRFv2PlusLoadTestConsumer - if cfg.ExistingEnvConfig.CreateFundSubsAndAddConsumers { - linkToken, err := env.ContractLoader.LoadLINKToken(vrfv2PlusConfig.LinkAddress) + if *testConfig.VRFv2Plus.ExistingEnvConfig.CreateFundSubsAndAddConsumers { + linkToken, err := env.ContractLoader.LoadLINKToken(*vrfv2PlusConfig.Performance.LinkAddress) require.NoError(t, err) consumers, err = vrfv2plus.DeployVRFV2PlusConsumers(env.ContractDeployer, coordinator, 1) require.NoError(t, err) err = env.EVMClient.WaitForEvents() require.NoError(t, err, vrfv2plus.ErrWaitTXsComplete) l.Info(). - Str("Coordinator", cfg.ExistingEnvConfig.CoordinatorAddress). - Int("Number of Subs to create", vrfv2PlusConfig.NumberOfSubToCreate). + Str("Coordinator", *vrfv2PlusConfig.Performance.CoordinatorAddress). + Int("Number of Subs to create", *vrfv2PlusConfig.General.NumberOfSubToCreate). Msg("Creating and funding subscriptions, deploying and adding consumers to subs") subIDs, err = vrfv2plus.CreateFundSubsAndAddConsumers( env, - vrfv2PlusConfig, + big.NewFloat(*testConfig.GetVRFv2PlusConfig().General.SubscriptionFundingAmountNative), + big.NewFloat(*testConfig.GetVRFv2PlusConfig().General.SubscriptionFundingAmountLink), linkToken, coordinator, consumers, - vrfv2PlusConfig.NumberOfSubToCreate, + *vrfv2PlusConfig.General.NumberOfSubToCreate, + vrfv2plus_config.BillingType(*vrfv2PlusConfig.General.SubscriptionBillingType), ) require.NoError(t, err) } else { - consumer, err := env.ContractLoader.LoadVRFv2PlusLoadTestConsumer(vrfv2PlusConfig.ConsumerAddress) + consumer, err := env.ContractLoader.LoadVRFv2PlusLoadTestConsumer(*vrfv2PlusConfig.Performance.ConsumerAddress) require.NoError(t, err) consumers = append(consumers, consumer) var ok bool - subID, ok := new(big.Int).SetString(vrfv2PlusConfig.SubID, 10) + subID := big.NewInt(int64(*vrfv2PlusConfig.Performance.SubID)) require.True(t, ok) subIDs = append(subIDs, subID) } - err = FundNodesIfNeeded(cfg, env.EVMClient, l) + err = FundNodesIfNeeded(&testConfig, env.EVMClient, l) require.NoError(t, err) vrfv2PlusContracts = &vrfv2plus.VRFV2_5Contracts{ @@ -155,7 +151,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { VRFV2PlusKeyData: vrfv2plus.VRFV2PlusKeyData{ VRFKey: nil, EncodedProvingKey: [2]*big.Int{}, - KeyHash: common.HexToHash(vrfv2PlusConfig.KeyHash), + KeyHash: common.HexToHash(*vrfv2PlusConfig.Performance.KeyHash), }, VRFJob: nil, PrimaryEthAddress: "", @@ -164,28 +160,28 @@ func TestVRFV2PlusPerformance(t *testing.T) { } else { //todo: temporary solution with envconfig and toml config until VRF-662 is implemented - vrfv2PlusConfig.ChainlinkNodeFunding = cfg.NewEnvConfig.NodeSendingKeyFunding - vrfv2PlusConfig.SubscriptionFundingAmountLink = cfg.NewEnvConfig.Funding.SubFundsLink - vrfv2PlusConfig.SubscriptionFundingAmountNative = cfg.NewEnvConfig.Funding.SubFundsNative + testConfig.Common.ChainlinkNodeFunding = testConfig.VRFv2.NewEnvConfig.NodeSendingKeyFunding + vrfv2PlusConfig.General.SubscriptionFundingAmountLink = testConfig.VRFv2Plus.NewEnvConfig.Funding.SubFundsLink + vrfv2PlusConfig.General.SubscriptionFundingAmountNative = testConfig.VRFv2Plus.NewEnvConfig.Funding.SubFundsNative - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + network, err := actions.EthereumNetworkConfigFromConfig(l, &testConfig) require.NoError(t, err, "Error building ethereum network config") - env, err = test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&testConfig). WithPrivateEthereumNetwork(network). WithCLNodes(1). - WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). + WithFunding(big.NewFloat(*testConfig.Common.ChainlinkNodeFunding)). WithCustomCleanup( func() { - teardown(t, vrfv2PlusContracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, testType, vrfv2PlusConfig) + teardown(t, vrfv2PlusContracts.LoadTestConsumers[0], lc, updatedLabels, testReporter, string(testType), &testConfig) if env.EVMClient.NetworkSimulated() { l.Info(). Str("Network Name", env.EVMClient.GetNetworkName()). Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") } else { - if cfg.Common.CancelSubsAfterTestRun { + if *testConfig.VRFv2Plus.Common.CancelSubsAfterTestRun { //cancel subs and return funds to sub owner cancelSubsAndReturnFunds(subIDs, l) } @@ -200,7 +196,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { env.ParallelTransactions(true) - mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(vrfv2PlusConfig.LinkNativeFeedResponse)) + mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(*vrfv2PlusConfig.General.LinkNativeFeedResponse)) require.NoError(t, err, "error deploying mock ETH/LINK feed") linkToken, err := actions.DeployLINKToken(env.ContractDeployer) @@ -208,12 +204,12 @@ func TestVRFV2PlusPerformance(t *testing.T) { vrfv2PlusContracts, subIDs, vrfv2PlusData, err = vrfv2plus.SetupVRFV2_5Environment( env, - vrfv2PlusConfig, + &testConfig, linkToken, mockETHLinkFeed, 0, 1, - vrfv2PlusConfig.NumberOfSubToCreate, + *vrfv2PlusConfig.General.NumberOfSubToCreate, l, ) require.NoError(t, err, "error setting up VRF v2_5 env") @@ -231,16 +227,16 @@ func TestVRFV2PlusPerformance(t *testing.T) { T: t, LoadType: wasp.RPS, GenName: "gun", - RateLimitUnitDuration: vrfv2PlusConfig.RateLimitUnitDuration, + RateLimitUnitDuration: vrfv2PlusConfig.Performance.RateLimitUnitDuration.Duration, Gun: NewSingleHashGun( vrfv2PlusContracts, vrfv2PlusData.KeyHash, subIDs, - vrfv2PlusConfig, + &testConfig, l, ), Labels: labels, - LokiConfig: lokiConfig, + LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), CallTimeout: 2 * time.Minute, } require.Len(t, vrfv2PlusContracts.LoadTestConsumers, 1, "only one consumer should be created for Load Test") @@ -251,10 +247,9 @@ func TestVRFV2PlusPerformance(t *testing.T) { // is our "job" stable at all, no memory leaks, no flaking performance under some RPS? t.Run("vrfv2plus performance test", func(t *testing.T) { - singleFeedConfig.Schedule = wasp.Plain( - vrfv2PlusConfig.RPS, - vrfv2PlusConfig.TestDuration, + *vrfv2PlusConfig.Performance.RPS, + vrfv2PlusConfig.Performance.TestDuration.Duration, ) _, err = wasp.NewProfile(). Add(wasp.NewGenerator(singleFeedConfig)). @@ -297,15 +292,16 @@ func cancelSubsAndReturnFunds(subIDs []*big.Int, l zerolog.Logger) { } } -func FundNodesIfNeeded(cfg *PerformanceConfig, client blockchain.EVMClient, l zerolog.Logger) error { - if cfg.ExistingEnvConfig.NodeSendingKeyFundingMin > 0 { +func FundNodesIfNeeded(vrfv2plusTestConfig tc.VRFv2PlusTestConfig, client blockchain.EVMClient, l zerolog.Logger) error { + cfg := vrfv2plusTestConfig.GetVRFv2PlusConfig() + if *cfg.ExistingEnvConfig.NodeSendingKeyFundingMin > 0 { for _, sendingKey := range cfg.ExistingEnvConfig.NodeSendingKeys { address := common.HexToAddress(sendingKey) sendingKeyBalance, err := client.BalanceAt(context.Background(), address) if err != nil { return err } - fundingAtLeast := conversions.EtherToWei(big.NewFloat(cfg.ExistingEnvConfig.NodeSendingKeyFundingMin)) + fundingAtLeast := conversions.EtherToWei(big.NewFloat(*cfg.ExistingEnvConfig.NodeSendingKeyFundingMin)) fundingToSendWei := new(big.Int).Sub(fundingAtLeast, sendingKeyBalance) fundingToSendEth := conversions.WeiToEther(fundingToSendWei) if fundingToSendWei.Cmp(big.NewInt(0)) == 1 { @@ -338,7 +334,7 @@ func teardown( updatedLabels map[string]string, testReporter *testreporters.VRFV2PlusTestReporter, testType string, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + testConfig *tc.TestConfig, ) { //send final results to Loki metrics := GetLoadTestMetrics(consumer) @@ -351,11 +347,11 @@ func teardown( metrics.AverageFulfillmentInMillions, metrics.SlowestFulfillment, metrics.FastestFulfillment, - vrfv2PlusConfig, + testConfig, ) // send Slack notification - err := testReporter.SendSlackNotification(t, nil) + err := testReporter.SendSlackNotification(t, nil, testConfig) if err != nil { log.Warn().Err(err).Msg("Error sending Slack notification") } diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index 6603fc1685d..584a9fbc75e 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -5,30 +5,37 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" - "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestVersionUpgrade(t *testing.T) { t.Parallel() + + config, err := tc.GetConfig("Migration", tc.Node) + require.NoError(t, err, "Error getting config") + + err = config.ChainlinkUpgradeImage.Validate() + require.NoError(t, err, "Error validating upgrade image") + env, err := test_env.NewCLTestEnvBuilder(). + WithTestConfig(&config). WithTestInstance(t). WithStandardCleanup(). WithGeth(). WithCLNodes(1). + WithStandardCleanup(). Build() require.NoError(t, err) - upgradeImage, err := osutil.GetEnv("UPGRADE_IMAGE") - require.NoError(t, err, "Error getting upgrade image") - upgradeVersion, err := osutil.GetEnv("UPGRADE_VERSION") - require.NoError(t, err, "Error getting upgrade version") + // just restarting CL container with the same name, DB is still the same + // // [Database] // MigrateOnStartup = true // // by default - err = env.ClCluster.Nodes[0].UpgradeVersion(upgradeImage, upgradeVersion) + err = env.ClCluster.Nodes[0].UpgradeVersion(*config.ChainlinkUpgradeImage.Image, *config.ChainlinkUpgradeImage.Version) require.NoError(t, err) } diff --git a/integration-tests/performance/cron_test.go b/integration-tests/performance/cron_test.go deleted file mode 100644 index 38d861cee07..00000000000 --- a/integration-tests/performance/cron_test.go +++ /dev/null @@ -1,139 +0,0 @@ -package performance - -import ( - "fmt" - "os" - "strings" - "testing" - "time" - - "github.com/google/uuid" - "github.com/onsi/gomega" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - - "github.com/smartcontractkit/chainlink-testing-framework/networks" - - "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/testreporters" - "github.com/smartcontractkit/chainlink/integration-tests/testsetups" -) - -func TestMain(m *testing.M) { - os.Exit(m.Run()) -} - -func CleanupPerformanceTest( - t *testing.T, - testEnvironment *environment.Environment, - chainlinkNodes []*client.ChainlinkK8sClient, - testReporter testreporters.ChainlinkProfileTestReporter, - chainClient blockchain.EVMClient, -) { - if chainClient != nil { - chainClient.GasStats().PrintStats() - } - err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, &testReporter, zapcore.PanicLevel, chainClient) - require.NoError(t, err, "Error tearing down environment") -} - -func TestCronPerformance(t *testing.T) { - testEnvironment := setupCronTest(t) - if testEnvironment.WillUseRemoteRunner() { - return - } - - chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) - require.NoError(t, err, "Connecting to chainlink nodes shouldn't fail") - mockServer, err := ctfClient.ConnectMockServer(testEnvironment) - require.NoError(t, err, "Creating mockserver client shouldn't fail") - chainlinkNode := chainlinkNodes[0] - err = mockServer.SetValuePath("/variable", 5) - require.NoError(t, err, "Setting value path in mockserver shouldn't fail") - - profileFunction := func(chainlinkNode *client.ChainlinkClient) { - if chainlinkNode != chainlinkNodes[len(chainlinkNodes)-1].ChainlinkClient { - // Not the last node, hence not all nodes started profiling yet. - return - } - bta := &client.BridgeTypeAttributes{ - Name: fmt.Sprintf("variable-%s", uuid.New().String()), - URL: fmt.Sprintf("%s/variable", mockServer.Config.ClusterURL), - RequestData: "{}", - } - err = chainlinkNode.MustCreateBridge(bta) - require.NoError(t, err, "Creating bridge in chainlink node shouldn't fail") - - job, err := chainlinkNode.MustCreateJob(&client.CronJobSpec{ - Schedule: "CRON_TZ=UTC * * * * * *", - ObservationSource: client.ObservationSourceSpecBridge(bta), - }) - require.NoError(t, err, "Creating Cron Job in chainlink node shouldn't fail") - - gom := gomega.NewGomegaWithT(t) - gom.Eventually(func(g gomega.Gomega) { - jobRuns, err := chainlinkNode.MustReadRunsByJob(job.Data.ID) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Reading Job run data shouldn't fail") - - g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 5), "Expected number of job runs to be greater than 5, but got %d", len(jobRuns.Data)) - - for _, jr := range jobRuns.Data { - g.Expect(jr.Attributes.Errors).Should(gomega.Equal([]interface{}{nil}), "Job run %s shouldn't have errors", jr.ID) - } - }, "2m", "1s").Should(gomega.Succeed()) - } - - profileTest := testsetups.NewChainlinkProfileTest(testsetups.ChainlinkProfileTestInputs{ - ProfileFunction: profileFunction, - ProfileDuration: 30 * time.Second, - ChainlinkNodes: []*client.ChainlinkK8sClient{chainlinkNode}, - }) - // Register cleanup for any test - t.Cleanup(func() { - CleanupPerformanceTest(t, testEnvironment, chainlinkNodes, profileTest.TestReporter, nil) - }) - profileTest.Setup(testEnvironment) - profileTest.Run() -} - -func setupCronTest(t *testing.T) (testEnvironment *environment.Environment) { - logging.Init() - network := networks.MustGetSelectedNetworksFromEnv()[0] - evmConfig := ethereum.New(nil) - if !network.Simulated { - evmConfig = ethereum.New(ðereum.Props{ - NetworkName: network.Name, - Simulated: network.Simulated, - WsURLs: network.URLs, - }) - } - baseTOML := `[WebServer] -HTTPWriteTimout = '300s'` - cd := chainlink.New(0, map[string]interface{}{ - "replicas": 1, - "toml": networks.AddNetworksConfig(baseTOML, network), - }) - - testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("performance-cron-%s", strings.ReplaceAll(strings.ToLower(network.Name), " ", "-")), - Test: t, - PreventPodEviction: true, - }). - AddHelm(mockservercfg.New(nil)). - AddHelm(mockserver.New(nil)). - AddHelm(evmConfig). - AddHelm(cd) - err := testEnvironment.Run() - require.NoError(t, err, "Error launching test environment") - return testEnvironment -} diff --git a/integration-tests/performance/directrequest_test.go b/integration-tests/performance/directrequest_test.go deleted file mode 100644 index 0fe1ca37e15..00000000000 --- a/integration-tests/performance/directrequest_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package performance - -import ( - "fmt" - "math/big" - "strings" - "testing" - "time" - - "github.com/onsi/gomega" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - - "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/testsetups" - - "github.com/google/uuid" -) - -func TestDirectRequestPerformance(t *testing.T) { - l := logging.GetTestLogger(t) - testEnvironment := setupDirectRequestTest(t) - if testEnvironment.WillUseRemoteRunner() { - return - } - - chainClient, err := blockchain.NewEVMClient(blockchain.SimulatedEVMNetwork, testEnvironment, l) - require.NoError(t, err, "Connecting to blockchain nodes shouldn't fail") - contractDeployer, err := contracts.NewContractDeployer(chainClient, l) - require.NoError(t, err, "Deploying contracts shouldn't fail") - chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) - require.NoError(t, err, "Connecting to chainlink nodes shouldn't fail") - mockServerClient, err := ctfClient.ConnectMockServer(testEnvironment) - require.NoError(t, err, "Error connecting to mock server") - - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, big.NewFloat(.01)) - require.NoError(t, err, "Funding chainlink nodes with ETH shouldn't fail") - - lt, err := contractDeployer.DeployLinkTokenContract() - require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") - oracle, err := contractDeployer.DeployOracle(lt.Address()) - require.NoError(t, err, "Deploying Oracle Contract shouldn't fail") - consumer, err := contractDeployer.DeployAPIConsumer(lt.Address()) - require.NoError(t, err, "Deploying Consumer Contract shouldn't fail") - err = chainClient.SetDefaultWallet(0) - require.NoError(t, err, "Setting default wallet shouldn't fail") - err = lt.Transfer(consumer.Address(), big.NewInt(2e18)) - require.NoError(t, err, "Transferring %d to consumer contract shouldn't fail", big.NewInt(2e18)) - - err = mockServerClient.SetValuePath("/variable", 5) - require.NoError(t, err, "Setting mockserver value path shouldn't fail") - - jobUUID := uuid.New() - - bta := client.BridgeTypeAttributes{ - Name: fmt.Sprintf("five-%s", jobUUID.String()), - URL: fmt.Sprintf("%s/variable", mockServerClient.Config.ClusterURL), - } - err = chainlinkNodes[0].MustCreateBridge(&bta) - require.NoError(t, err, "Creating bridge shouldn't fail") - - os := &client.DirectRequestTxPipelineSpec{ - BridgeTypeAttributes: bta, - DataPath: "data,result", - } - ost, err := os.String() - require.NoError(t, err, "Building observation source spec shouldn't fail") - - _, err = chainlinkNodes[0].MustCreateJob(&client.DirectRequestJobSpec{ - Name: "direct_request", - MinIncomingConfirmations: "1", - ContractAddress: oracle.Address(), - EVMChainID: chainClient.GetChainID().String(), - ExternalJobID: jobUUID.String(), - ObservationSource: ost, - }) - require.NoError(t, err, "Creating direct_request job shouldn't fail") - - profileFunction := func(chainlinkNode *client.ChainlinkClient) { - if chainlinkNode != chainlinkNodes[len(chainlinkNodes)-1].ChainlinkClient { - // Not the last node, hence not all nodes started profiling yet. - return - } - jobUUIDReplaces := strings.Replace(jobUUID.String(), "-", "", 4) - var jobID [32]byte - copy(jobID[:], jobUUIDReplaces) - err = consumer.CreateRequestTo( - oracle.Address(), - jobID, - big.NewInt(1e18), - fmt.Sprintf("%s/variable", mockServerClient.Config.ClusterURL), - "data,result", - big.NewInt(100), - ) - require.NoError(t, err, "Calling oracle contract shouldn't fail") - - gom := gomega.NewGomegaWithT(t) - gom.Eventually(func(g gomega.Gomega) { - d, err := consumer.Data(testcontext.Get(t)) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting data from consumer contract shouldn't fail") - g.Expect(d).ShouldNot(gomega.BeNil(), "Expected the initial on chain data to be nil") - l.Debug().Int64("Data", d.Int64()).Msg("Found on chain") - g.Expect(d.Int64()).Should(gomega.BeNumerically("==", 5), "Expected the on-chain data to be 5, but found %d", d.Int64()) - }, "2m", "1s").Should(gomega.Succeed()) - } - - profileTest := testsetups.NewChainlinkProfileTest(testsetups.ChainlinkProfileTestInputs{ - ProfileFunction: profileFunction, - ProfileDuration: 30 * time.Second, - ChainlinkNodes: chainlinkNodes, - }) - profileTest.Setup(testEnvironment) - t.Cleanup(func() { - CleanupPerformanceTest(t, testEnvironment, chainlinkNodes, profileTest.TestReporter, chainClient) - }) - profileTest.Run() -} - -func setupDirectRequestTest(t *testing.T) (testEnvironment *environment.Environment) { - network := networks.MustGetSelectedNetworksFromEnv()[0] - evmConfig := ethereum.New(nil) - if !network.Simulated { - evmConfig = ethereum.New(ðereum.Props{ - NetworkName: network.Name, - Simulated: network.Simulated, - WsURLs: network.URLs, - }) - } - baseTOML := `[WebServer] -HTTPWriteTimout = '300s'` - cd := chainlink.New(0, map[string]interface{}{ - "replicas": 1, - "toml": networks.AddNetworksConfig(baseTOML, network), - }) - - testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("performance-cron-%s", strings.ReplaceAll(strings.ToLower(network.Name), " ", "-")), - Test: t, - PreventPodEviction: true, - }). - AddHelm(mockservercfg.New(nil)). - AddHelm(mockserver.New(nil)). - AddHelm(evmConfig). - AddHelm(cd) - err := testEnvironment.Run() - require.NoError(t, err, "Error launching test environment") - return testEnvironment -} diff --git a/integration-tests/performance/flux_test.go b/integration-tests/performance/flux_test.go deleted file mode 100644 index 5fa31b626ae..00000000000 --- a/integration-tests/performance/flux_test.go +++ /dev/null @@ -1,207 +0,0 @@ -package performance - -import ( - "fmt" - "math/big" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/google/uuid" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - - "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/testsetups" -) - -func TestFluxPerformance(t *testing.T) { - l := logging.GetTestLogger(t) - testEnvironment, testNetwork := setupFluxTest(t) - if testEnvironment.WillUseRemoteRunner() { - return - } - - chainClient, err := blockchain.NewEVMClient(testNetwork, testEnvironment, l) - require.NoError(t, err, "Connecting to blockchain nodes shouldn't fail") - contractDeployer, err := contracts.NewContractDeployer(chainClient, l) - require.NoError(t, err, "Deploying contracts shouldn't fail") - chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) - require.NoError(t, err, "Connecting to chainlink nodes shouldn't fail") - nodeAddresses, err := actions.ChainlinkNodeAddresses(chainlinkNodes) - require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") - mockServer, err := ctfClient.ConnectMockServer(testEnvironment) - require.NoError(t, err, "Creating mock server client shouldn't fail") - - chainClient.ParallelTransactions(true) - - adapterUUID := uuid.New().String() - adapterPath := fmt.Sprintf("/variable-%s", adapterUUID) - err = mockServer.SetValuePath(adapterPath, 1e5) - require.NoError(t, err, "Setting mockserver value path shouldn't fail") - - linkToken, err := contractDeployer.DeployLinkTokenContract() - require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") - fluxInstance, err := contractDeployer.DeployFluxAggregatorContract(linkToken.Address(), contracts.DefaultFluxAggregatorOptions()) - require.NoError(t, err, "Deploying Flux Aggregator Contract shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Failed waiting for deployment of flux aggregator contract") - - err = linkToken.Transfer(fluxInstance.Address(), big.NewInt(1e18)) - require.NoError(t, err, "Funding Flux Aggregator Contract shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Failed waiting for funding of flux aggregator contract") - - err = fluxInstance.UpdateAvailableFunds() - require.NoError(t, err, "Updating the available funds on the Flux Aggregator Contract shouldn't fail") - - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, big.NewFloat(.02)) - require.NoError(t, err, "Funding chainlink nodes with ETH shouldn't fail") - - err = fluxInstance.SetOracles( - contracts.FluxAggregatorSetOraclesOptions{ - AddList: nodeAddresses, - RemoveList: []common.Address{}, - AdminList: nodeAddresses, - MinSubmissions: 3, - MaxSubmissions: 3, - RestartDelayRounds: 0, - }) - require.NoError(t, err, "Setting oracle options in the Flux Aggregator contract shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail") - oracles, err := fluxInstance.GetOracles(testcontext.Get(t)) - require.NoError(t, err, "Getting oracle details from the Flux aggregator contract shouldn't fail") - l.Info().Str("Oracles", strings.Join(oracles, ",")).Msg("Oracles set") - - adapterFullURL := fmt.Sprintf("%s%s", mockServer.Config.ClusterURL, adapterPath) - bta := &client.BridgeTypeAttributes{ - Name: fmt.Sprintf("variable-%s", adapterUUID), - URL: adapterFullURL, - } - for i, n := range chainlinkNodes { - err = n.MustCreateBridge(bta) - require.NoError(t, err, "Creating bridge shouldn't fail for node %d", i+1) - - fluxSpec := &client.FluxMonitorJobSpec{ - Name: fmt.Sprintf("flux-monitor-%s", adapterUUID), - ContractAddress: fluxInstance.Address(), - EVMChainID: chainClient.GetChainID().String(), - Threshold: 0, - AbsoluteThreshold: 0, - PollTimerPeriod: 15 * time.Second, // min 15s - IdleTimerDisabled: true, - ObservationSource: client.ObservationSourceSpecBridge(bta), - } - _, err = n.MustCreateJob(fluxSpec) - require.NoError(t, err, "Creating flux job shouldn't fail for node %d", i+1) - } - - profileFunction := func(chainlinkNode *client.ChainlinkClient) { - if chainlinkNode != chainlinkNodes[len(chainlinkNodes)-1].ChainlinkClient { - // Not the last node, hence not all nodes started profiling yet. - return - } - fluxRoundTimeout := 2 * time.Minute - fluxRound := contracts.NewFluxAggregatorRoundConfirmer(fluxInstance, big.NewInt(1), fluxRoundTimeout, l) - chainClient.AddHeaderEventSubscription(fluxInstance.Address(), fluxRound) - err = chainClient.WaitForEvents() - require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail") - data, err := fluxInstance.GetContractData(testcontext.Get(t)) - require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail") - l.Info().Interface("Data", data).Msg("Round data") - require.Equal(t, int64(1e5), data.LatestRoundData.Answer.Int64(), - "Expected latest round answer to be %d, but found %d", int64(1e5), data.LatestRoundData.Answer.Int64()) - require.Equal(t, int64(1), data.LatestRoundData.RoundId.Int64(), - "Expected latest round id to be %d, but found %d", int64(1), data.LatestRoundData.RoundId.Int64()) - require.Equal(t, int64(1), data.LatestRoundData.AnsweredInRound.Int64(), - "Expected latest round's answered in round to be %d, but found %d", int64(1), data.LatestRoundData.AnsweredInRound.Int64()) - require.Equal(t, int64(999999999999999997), data.AvailableFunds.Int64(), - "Expected available funds to be %d, but found %d", int64(999999999999999997), data.AvailableFunds.Int64()) - require.Equal(t, int64(3), data.AllocatedFunds.Int64(), - "Expected allocated funds to be %d, but found %d", int64(3), data.AllocatedFunds.Int64()) - - fluxRound = contracts.NewFluxAggregatorRoundConfirmer(fluxInstance, big.NewInt(2), fluxRoundTimeout, l) - chainClient.AddHeaderEventSubscription(fluxInstance.Address(), fluxRound) - err = mockServer.SetValuePath(adapterPath, 1e10) - require.NoError(t, err, "Setting value path in mock server shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail") - data, err = fluxInstance.GetContractData(testcontext.Get(t)) - require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail") - require.Equal(t, int64(1e10), data.LatestRoundData.Answer.Int64(), - "Expected latest round answer to be %d, but found %d", int64(1e10), data.LatestRoundData.Answer.Int64()) - require.Equal(t, int64(2), data.LatestRoundData.RoundId.Int64(), - "Expected latest round id to be %d, but found %d", int64(2), data.LatestRoundData.RoundId.Int64()) - require.Equal(t, int64(999999999999999994), data.AvailableFunds.Int64(), - "Expected available funds to be %d, but found %d", int64(999999999999999994), data.AvailableFunds.Int64()) - require.Equal(t, int64(6), data.AllocatedFunds.Int64(), - "Expected allocated funds to be %d, but found %d", int64(6), data.AllocatedFunds.Int64()) - l.Info().Interface("data", data).Msg("Round data") - - for _, oracleAddr := range nodeAddresses { - payment, _ := fluxInstance.WithdrawablePayment(testcontext.Get(t), oracleAddr) - require.Equal(t, int64(2), payment.Int64(), - "Expected flux aggregator contract's withdrawable payment to be %d, but found %d", int64(2), payment.Int64()) - } - } - - profileTest := testsetups.NewChainlinkProfileTest(testsetups.ChainlinkProfileTestInputs{ - ProfileFunction: profileFunction, - ProfileDuration: 30 * time.Second, - ChainlinkNodes: chainlinkNodes, - }) - // Register cleanup - t.Cleanup(func() { - CleanupPerformanceTest(t, testEnvironment, chainlinkNodes, profileTest.TestReporter, chainClient) - }) - profileTest.Setup(testEnvironment) - profileTest.Run() -} - -func setupFluxTest(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) { - testNetwork = networks.MustGetSelectedNetworksFromEnv()[0] - evmConf := ethereum.New(nil) - if !testNetwork.Simulated { - evmConf = ethereum.New(ðereum.Props{ - NetworkName: testNetwork.Name, - Simulated: testNetwork.Simulated, - WsURLs: testNetwork.URLs, - }) - } - baseTOML := `[WebServer] -HTTPWriteTimout = '300s' - -[OCR] -Enabled = true` - cd := chainlink.New(0, map[string]interface{}{ - "replicas": 3, - "toml": networks.AddNetworksConfig(baseTOML, testNetwork), - }) - - testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("performance-flux-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")), - Test: t, - PreventPodEviction: true, - }). - AddHelm(mockservercfg.New(nil)). - AddHelm(mockserver.New(nil)). - AddHelm(evmConf). - AddHelm(cd) - err := testEnvironment.Run() - require.NoError(t, err, "Error running test environment") - return testEnvironment, testNetwork -} diff --git a/integration-tests/performance/keeper_test.go b/integration-tests/performance/keeper_test.go deleted file mode 100644 index ac6e9e6a579..00000000000 --- a/integration-tests/performance/keeper_test.go +++ /dev/null @@ -1,194 +0,0 @@ -package performance - -//revive:disable:dot-imports -import ( - "fmt" - "math/big" - "strings" - "testing" - "time" - - "github.com/onsi/gomega" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - eth "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - - "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" - "github.com/smartcontractkit/chainlink/integration-tests/testsetups" -) - -var keeperDefaultRegistryConfig = contracts.KeeperRegistrySettings{ - PaymentPremiumPPB: uint32(200000000), - FlatFeeMicroLINK: uint32(0), - BlockCountPerTurn: big.NewInt(10), - CheckGasLimit: uint32(2500000), - StalenessSeconds: big.NewInt(90000), - GasCeilingMultiplier: uint16(1), - MinUpkeepSpend: big.NewInt(0), - MaxPerformGas: uint32(5000000), - FallbackGasPrice: big.NewInt(2e11), - FallbackLinkPrice: big.NewInt(2e18), - MaxCheckDataSize: uint32(5000), - MaxPerformDataSize: uint32(5000), -} - -func TestKeeperPerformance(t *testing.T) { - l := logging.GetTestLogger(t) - testEnvironment, chainClient, chainlinkNodes, contractDeployer, linkToken := setupKeeperTest(t, "basic-smoke") - if testEnvironment.WillUseRemoteRunner() { - return - } - registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( - t, - ethereum.RegistryVersion_1_1, - keeperDefaultRegistryConfig, - 1, - uint32(2500000), - linkToken, - contractDeployer, - chainClient, - big.NewInt(9e18), - ) - gom := gomega.NewGomegaWithT(t) - - profileFunction := func(chainlinkNode *client.ChainlinkClient) { - if chainlinkNode != chainlinkNodes[len(chainlinkNodes)-1].ChainlinkClient { - // Not the last node, hence not all nodes started profiling yet. - return - } - actions.CreateKeeperJobs(t, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) - err := chainClient.WaitForEvents() - require.NoError(t, err, "Error creating keeper jobs") - - gom.Eventually(func(g gomega.Gomega) { - // Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 10 - for i := 0; i < len(upkeepIDs); i++ { - counter, err := consumers[i].Counter(testcontext.Get(t)) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(10)), - "Expected consumer counter to be greater than 10, but got %d", counter.Int64()) - l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed") - } - }, "5m", "1s").Should(gomega.Succeed()) - - // Cancel all the registered upkeeps via the registry - for i := 0; i < len(upkeepIDs); i++ { - err = registry.CancelUpkeep(upkeepIDs[i]) - require.NoError(t, err, "Could not cancel upkeep at index %d", i) - } - - err = chainClient.WaitForEvents() - require.NoError(t, err, "Error waiting for upkeeps to be cancelled") - - var countersAfterCancellation = make([]*big.Int, len(upkeepIDs)) - - for i := 0; i < len(upkeepIDs); i++ { - // Obtain the amount of times the upkeep has been executed so far - countersAfterCancellation[i], err = consumers[i].Counter(testcontext.Get(t)) - require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) - l.Info().Int("Index", i).Int64("Upkeeps Performed", countersAfterCancellation[i].Int64()).Msg("Cancelled Upkeep") - } - - gom.Consistently(func(g gomega.Gomega) { - for i := 0; i < len(upkeepIDs); i++ { - // Expect the counter to remain constant because the upkeep was cancelled, so it shouldn't increase anymore - latestCounter, err := consumers[i].Counter(testcontext.Get(t)) - require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterCancellation[i].Int64()), - "Expected consumer counter to remain constant at %d, but got %d", - countersAfterCancellation[i].Int64(), latestCounter.Int64()) - } - }, "1m", "1s").Should(gomega.Succeed()) - } - profileTest := testsetups.NewChainlinkProfileTest(testsetups.ChainlinkProfileTestInputs{ - ProfileFunction: profileFunction, - ProfileDuration: 10 * time.Second, - ChainlinkNodes: chainlinkNodes, - }) - // Register cleanup - t.Cleanup(func() { - CleanupPerformanceTest(t, testEnvironment, chainlinkNodes, profileTest.TestReporter, chainClient) - }) - profileTest.Setup(testEnvironment) - profileTest.Run() -} - -func setupKeeperTest( - t *testing.T, - testName string, -) ( - *environment.Environment, - blockchain.EVMClient, - []*client.ChainlinkK8sClient, - contracts.ContractDeployer, - contracts.LinkToken, -) { - network := networks.MustGetSelectedNetworksFromEnv()[0] - evmConfig := eth.New(nil) - if !network.Simulated { - evmConfig = eth.New(ð.Props{ - NetworkName: network.Name, - Simulated: network.Simulated, - WsURLs: network.URLs, - }) - } - baseTOML := `[WebServer] -HTTPWriteTimout = '300s' - -[Keeper] -TurnLookBack = 0 - -[Keeper.Registry] -SyncInterval = '5s' -PerformGasOverhead = 150_000` - networkName := strings.ReplaceAll(strings.ToLower(network.Name), " ", "-") - cd := chainlink.New(0, map[string]interface{}{ - "replicas": 5, - "toml": networks.AddNetworksConfig(baseTOML, network), - }) - - testEnvironment := environment.New( - &environment.Config{ - NamespacePrefix: fmt.Sprintf("performance-keeper-%s-%s", testName, networkName), - Test: t, - PreventPodEviction: true, - }, - ). - AddHelm(mockservercfg.New(nil)). - AddHelm(mockserver.New(nil)). - AddHelm(evmConfig). - AddHelm(cd) - err := testEnvironment.Run() - require.NoError(t, err, "Error deploying test environment") - if testEnvironment.WillUseRemoteRunner() { - return testEnvironment, nil, nil, nil, nil - } - - l := logging.GetTestLogger(t) - chainClient, err := blockchain.NewEVMClient(network, testEnvironment, l) - require.NoError(t, err, "Connecting to blockchain nodes shouldn't fail") - contractDeployer, err := contracts.NewContractDeployer(chainClient, l) - require.NoError(t, err, "Deploying contracts shouldn't fail") - chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) - require.NoError(t, err, "Connecting to chainlink nodes shouldn't fail") - chainClient.ParallelTransactions(true) - - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, big.NewFloat(.5)) - require.NoError(t, err, "Funding Chainlink nodes shouldn't fail") - - linkToken, err := contractDeployer.DeployLinkTokenContract() - require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") - - return testEnvironment, chainClient, chainlinkNodes, contractDeployer, linkToken -} diff --git a/integration-tests/performance/ocr_test.go b/integration-tests/performance/ocr_test.go deleted file mode 100644 index 7e0ed0111d8..00000000000 --- a/integration-tests/performance/ocr_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package performance - -import ( - "fmt" - "math/big" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - - "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/testsetups" -) - -func TestOCRBasic(t *testing.T) { - t.Parallel() - testEnvironment, testNetwork := setupOCRTest(t) - if testEnvironment.WillUseRemoteRunner() { - return - } - l := logging.GetTestLogger(t) - chainClient, err := blockchain.NewEVMClient(testNetwork, testEnvironment, l) - require.NoError(t, err, "Connecting to blockchain nodes shouldn't fail") - contractDeployer, err := contracts.NewContractDeployer(chainClient, l) - require.NoError(t, err, "Deploying contracts shouldn't fail") - - chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) - require.NoError(t, err, "Connecting to chainlink nodes shouldn't fail") - bootstrapNode, workerNodes := chainlinkNodes[0], chainlinkNodes[1:] - mockServer, err := ctfClient.ConnectMockServer(testEnvironment) - require.NoError(t, err, "Creating mockserver clients shouldn't fail") - - chainClient.ParallelTransactions(true) - - linkTokenContract, err := contractDeployer.DeployLinkTokenContract() - require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") - - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, big.NewFloat(.05)) - require.NoError(t, err, "Error funding Chainlink nodes") - - ocrInstances, err := actions.DeployOCRContracts(1, linkTokenContract, contractDeployer, workerNodes, chainClient) - require.NoError(t, err) - err = chainClient.WaitForEvents() - require.NoError(t, err, "Error waiting for events") - - profileFunction := func(chainlinkNode *client.ChainlinkClient) { - err = actions.CreateOCRJobs(ocrInstances, bootstrapNode, workerNodes, 5, mockServer, chainClient.GetChainID().String()) - require.NoError(t, err) - err = actions.StartNewRound(1, ocrInstances, chainClient, l) - require.NoError(t, err) - - answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) - require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") - require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64()) - - err = mockServer.SetValuePath("ocr", 10) - require.NoError(t, err) - err = actions.StartNewRound(2, ocrInstances, chainClient, l) - require.NoError(t, err) - - answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) - require.NoError(t, err, "Error getting latest OCR answer") - require.Equal(t, int64(10), answer.Int64(), "Expected latest answer from OCR contract to be 10 but got %d", answer.Int64()) - } - profileTest := testsetups.NewChainlinkProfileTest(testsetups.ChainlinkProfileTestInputs{ - ProfileFunction: profileFunction, - ProfileDuration: time.Minute, - ChainlinkNodes: chainlinkNodes, - }) - t.Cleanup(func() { - CleanupPerformanceTest(t, testEnvironment, chainlinkNodes, profileTest.TestReporter, chainClient) - }) - profileTest.Setup(testEnvironment) - profileTest.Run() -} - -func setupOCRTest(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) { - testNetwork = networks.MustGetSelectedNetworksFromEnv()[0] - evmConfig := ethereum.New(nil) - if !testNetwork.Simulated { - evmConfig = ethereum.New(ðereum.Props{ - NetworkName: testNetwork.Name, - Simulated: testNetwork.Simulated, - WsURLs: testNetwork.URLs, - }) - } - baseTOML := `[OCR] -Enabled = true - -[P2P] -[P2P.V2] -AnnounceAddresses = ["0.0.0.0:6690"] -ListenAddresses = ["0.0.0.0:6690"]` - - cd := chainlink.New(0, map[string]interface{}{ - "replicas": 6, - "toml": networks.AddNetworksConfig(baseTOML, testNetwork), - }) - - testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("performance-ocr-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")), - Test: t, - PreventPodEviction: true, - }). - AddHelm(mockservercfg.New(nil)). - AddHelm(mockserver.New(nil)). - AddHelm(evmConfig). - AddHelm(cd) - err := testEnvironment.Run() - require.NoError(t, err, "Error running test environment") - return testEnvironment, testNetwork -} diff --git a/integration-tests/performance/vrf_test.go b/integration-tests/performance/vrf_test.go deleted file mode 100644 index cad4ea5eebd..00000000000 --- a/integration-tests/performance/vrf_test.go +++ /dev/null @@ -1,163 +0,0 @@ -package performance - -import ( - "fmt" - "math/big" - "strings" - "testing" - "time" - - "github.com/google/uuid" - "github.com/onsi/gomega" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - - "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/testsetups" -) - -func TestVRFBasic(t *testing.T) { - t.Parallel() - l := logging.GetTestLogger(t) - testEnvironment, testNetwork := setupVRFTest(t) - if testEnvironment.WillUseRemoteRunner() { - return - } - - chainClient, err := blockchain.NewEVMClient(testNetwork, testEnvironment, l) - require.NoError(t, err, "Connecting client shouldn't fail") - cd, err := contracts.NewContractDeployer(chainClient, l) - require.NoError(t, err, "Deploying contracts shouldn't fail") - chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) - require.NoError(t, err, "Connecting to chainlink nodes shouldn't fail") - chainClient.ParallelTransactions(true) - - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, big.NewFloat(.01)) - require.NoError(t, err, "Funding chainlink nodes with ETH shouldn't fail") - - lt, err := cd.DeployLinkTokenContract() - require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") - bhs, err := cd.DeployBlockhashStore() - require.NoError(t, err, "Deploying Blockhash store shouldn't fail") - coordinator, err := cd.DeployVRFCoordinator(lt.Address(), bhs.Address()) - require.NoError(t, err, "Deploying VRF coordinator shouldn't fail") - consumer, err := cd.DeployVRFConsumer(lt.Address(), coordinator.Address()) - require.NoError(t, err, "Deploying VRF consumer contract shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Failed to wait for VRF setup contracts to deploy") - - err = lt.Transfer(consumer.Address(), big.NewInt(2e18)) - require.NoError(t, err, "Funding consumer contract shouldn't fail") - _, err = cd.DeployVRFContract() - require.NoError(t, err, "Deploying VRF contract shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail") - - profileFunction := func(chainlinkNode *client.ChainlinkClient) { - nodeKey, err := chainlinkNode.MustCreateVRFKey() - require.NoError(t, err, "Creating VRF key shouldn't fail") - l.Debug().Interface("Key JSON", nodeKey).Msg("Created proving key") - pubKeyCompressed := nodeKey.Data.ID - jobUUID := uuid.New() - os := &client.VRFTxPipelineSpec{ - Address: coordinator.Address(), - } - ost, err := os.String() - require.NoError(t, err, "Building observation source spec shouldn't fail") - job, err := chainlinkNode.MustCreateJob(&client.VRFJobSpec{ - Name: fmt.Sprintf("vrf-%s", jobUUID), - CoordinatorAddress: coordinator.Address(), - MinIncomingConfirmations: 1, - PublicKey: pubKeyCompressed, - ExternalJobID: jobUUID.String(), - ObservationSource: ost, - }) - require.NoError(t, err, "Creating VRF Job shouldn't fail") - - oracleAddr, err := chainlinkNode.PrimaryEthAddress() - require.NoError(t, err, "Getting primary ETH address of chainlink node shouldn't fail") - provingKey, err := actions.EncodeOnChainVRFProvingKey(*nodeKey) - require.NoError(t, err, "Encoding on-chain VRF Proving key shouldn't fail") - err = coordinator.RegisterProvingKey( - big.NewInt(1), - oracleAddr, - provingKey, - actions.EncodeOnChainExternalJobID(jobUUID), - ) - require.NoError(t, err, "Registering the on-chain VRF Proving key shouldn't fail") - encodedProvingKeys := make([][2]*big.Int, 0) - encodedProvingKeys = append(encodedProvingKeys, provingKey) - - requestHash, err := coordinator.HashOfKey(testcontext.Get(t), encodedProvingKeys[0]) - require.NoError(t, err, "Getting Hash of encoded proving keys shouldn't fail") - err = consumer.RequestRandomness(requestHash, big.NewInt(1)) - require.NoError(t, err, "Requesting randomness shouldn't fail") - - gom := gomega.NewGomegaWithT(t) - timeout := time.Minute * 2 - gom.Eventually(func(g gomega.Gomega) { - jobRuns, err := chainlinkNodes[0].MustReadRunsByJob(job.Data.ID) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail") - - out, err := consumer.RandomnessOutput(testcontext.Get(t)) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail") - // Checks that the job has actually run - g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1), - fmt.Sprintf("Expected the VRF job to run once or more after %s", timeout)) - - // TODO: This is an imperfect check, given it's a random number, it CAN be 0, but chances are unlikely. - // So we're just checking that the answer has changed to something other than the default (0) - // There's a better formula to ensure that VRF response is as expected, detailed under Technical Walkthrough. - // https://blog.chain.link/chainlink-vrf-on-chain-verifiable-randomness/ - g.Expect(out.Uint64()).ShouldNot(gomega.BeNumerically("==", 0), "Expected the VRF job give an answer other than 0") - l.Debug().Uint64("Output", out.Uint64()).Msg("Randomness fulfilled") - }, timeout, "1s").Should(gomega.Succeed()) - } - profileTest := testsetups.NewChainlinkProfileTest(testsetups.ChainlinkProfileTestInputs{ - ProfileFunction: profileFunction, - ProfileDuration: 30 * time.Second, - ChainlinkNodes: chainlinkNodes, - }) - t.Cleanup(func() { - CleanupPerformanceTest(t, testEnvironment, chainlinkNodes, profileTest.TestReporter, chainClient) - }) - profileTest.Setup(testEnvironment) - profileTest.Run() -} - -func setupVRFTest(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) { - testNetwork = networks.MustGetSelectedNetworksFromEnv()[0] - evmConfig := ethereum.New(nil) - if !testNetwork.Simulated { - evmConfig = ethereum.New(ðereum.Props{ - NetworkName: testNetwork.Name, - Simulated: testNetwork.Simulated, - WsURLs: testNetwork.URLs, - }) - } - baseTOML := `[WebServer] -HTTPWriteTimout = '300s'` - cd := chainlink.New(0, map[string]interface{}{ - "toml": networks.AddNetworksConfig(baseTOML, testNetwork), - }) - - testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("smoke-vrf-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")), - Test: t, - PreventPodEviction: true, - }). - AddHelm(evmConfig). - AddHelm(cd) - err := testEnvironment.Run() - require.NoError(t, err, "Error running test environment") - return testEnvironment, testNetwork -} diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index dae977d3eea..36b5d3eb985 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -12,6 +12,7 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/cdk8s/blockscout" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" @@ -24,6 +25,8 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) var ( @@ -47,9 +50,9 @@ HistoryDepth = 400 [EVM.GasEstimator] Mode = 'FixedPrice' LimitDefault = 5_000_000` - activeEVMNetwork = networks.MustGetSelectedNetworksFromEnv()[0] + defaultAutomationSettings = map[string]interface{}{ - "toml": networks.AddNetworkDetailedConfig(baseTOML, networkTOML, activeEVMNetwork), + "toml": "", "db": map[string]interface{}{ "stateful": false, "capacity": "1Gi", @@ -67,7 +70,7 @@ LimitDefault = 5_000_000` } defaultReorgEthereumSettings = &reorg.Props{ - NetworkName: activeEVMNetwork.Name, + NetworkName: "", NetworkType: "geth-reorg", Values: map[string]interface{}{ "geth": map[string]interface{}{ @@ -126,9 +129,9 @@ func TestAutomationReorg(t *testing.T) { l := logging.GetTestLogger(t) registryVersions := map[string]ethereum.KeeperRegistryVersion{ - "registry_2_0": ethereum.RegistryVersion_2_0, - "registry_2_1_conditional": ethereum.RegistryVersion_2_1, - "registry_2_1_logtrigger": ethereum.RegistryVersion_2_1, + "registry_2_0": ethereum.RegistryVersion_2_0, + // "registry_2_1_conditional": ethereum.RegistryVersion_2_1, + // "registry_2_1_logtrigger": ethereum.RegistryVersion_2_1, } for name, registryVersion := range registryVersions { @@ -136,22 +139,38 @@ func TestAutomationReorg(t *testing.T) { registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() - network := networks.MustGetSelectedNetworksFromEnv()[0] + config, err := tc.GetConfig("Reorg", tc.Automation) + if err != nil { + t.Fatal(err) + } + + network := networks.MustGetSelectedNetworkConfig(config.Network)[0] defaultAutomationSettings["replicas"] = numberOfNodes - cd := chainlink.New(0, defaultAutomationSettings) + defaultAutomationSettings["toml"] = networks.AddNetworkDetailedConfig(baseTOML, config.Pyroscope, networkTOML, network) + + var overrideFn = func(_ interface{}, target interface{}) { + ctf_config.MustConfigOverrideChainlinkVersion(config.ChainlinkImage, target) + ctf_config.MightConfigOverridePyroscopeKey(config.Pyroscope, target) + } + + cd := chainlink.NewWithOverride(0, defaultAutomationSettings, config.ChainlinkImage, overrideFn) + + ethSetting := defaultReorgEthereumSettings + ethSetting.NetworkName = network.Name + testEnvironment := environment. New(&environment.Config{ NamespacePrefix: fmt.Sprintf("automation-reorg-%d", automationReorgBlocks), TTL: time.Hour * 1, Test: t}). - AddHelm(reorg.New(defaultReorgEthereumSettings)). + AddHelm(reorg.New(ethSetting)). AddChart(blockscout.New(&blockscout.Props{ Name: "geth-blockscout", - WsURL: activeEVMNetwork.URL, - HttpURL: activeEVMNetwork.HTTPURLs[0]})). + WsURL: network.URL, + HttpURL: network.HTTPURLs[0]})). AddHelm(cd) - err := testEnvironment.Run() + err = testEnvironment.Run() require.NoError(t, err, "Error setting up test environment") if testEnvironment.WillUseRemoteRunner() { @@ -168,7 +187,7 @@ func TestAutomationReorg(t *testing.T) { // Register cleanup for any test t.Cleanup(func() { - err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, chainClient) + err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config, chainClient) require.NoError(t, err, "Error tearing down environment") }) diff --git a/integration-tests/reorg/reorg_test.go b/integration-tests/reorg/reorg_test.go deleted file mode 100644 index fc35047d0e4..00000000000 --- a/integration-tests/reorg/reorg_test.go +++ /dev/null @@ -1,228 +0,0 @@ -package reorg - -import ( - "fmt" - "math/big" - "os" - "strings" - "testing" - "time" - - "github.com/google/uuid" - "github.com/onsi/gomega" - "github.com/rs/zerolog/log" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/cdk8s/blockscout" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - - "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" -) - -const ( - baseDRTOML = ` -[Feature] -LogPoller = true -` - networkDRTOML = ` -Enabled = true -FinalityDepth = %s -LogPollInterval = '1s' - -[EVM.HeadTracker] -HistoryDepth = %s -` -) - -const ( - EVMFinalityDepth = "200" - EVMTrackerHistoryDepth = "400" - reorgBlocks = 10 - minIncomingConfirmations = "200" - timeout = "15m" - interval = "2s" -) - -var ( - networkSettings = blockchain.EVMNetwork{ - Name: "geth", - Simulated: true, - ChainID: 1337, - PrivateKeys: []string{ - "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - }, - ChainlinkTransactionLimit: 500000, - Timeout: blockchain.JSONStrDuration{Duration: 2 * time.Minute}, - MinimumConfirmations: 1, - GasEstimationBuffer: 10000, - } -) - -func TestMain(m *testing.M) { - os.Exit(m.Run()) -} - -func CleanupReorgTest( - t *testing.T, - testEnvironment *environment.Environment, - chainlinkNodes []*client.ChainlinkK8sClient, - chainClient blockchain.EVMClient, -) { - if chainClient != nil { - chainClient.GasStats().PrintStats() - } - err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, chainClient) - require.NoError(t, err, "Error tearing down environment") -} - -func TestDirectRequestReorg(t *testing.T) { - logging.Init() - l := logging.GetTestLogger(t) - testEnvironment := environment.New(&environment.Config{ - TTL: 1 * time.Hour, - Test: t, - }) - err := testEnvironment. - AddHelm(mockservercfg.New(nil)). - AddHelm(mockserver.New(nil)). - AddChart(blockscout.New(&blockscout.Props{ - WsURL: "ws://geth-ethereum-geth:8546", - HttpURL: "http://geth-ethereum-geth:8544", - })). - AddHelm(reorg.New(&reorg.Props{ - NetworkName: "geth", - NetworkType: "geth-reorg", - Values: map[string]interface{}{ - "geth": map[string]interface{}{ - "genesis": map[string]interface{}{ - "networkId": "1337", - }, - }, - }, - })). - Run() - require.NoError(t, err, "Error deploying test environment") - if testEnvironment.WillUseRemoteRunner() { - return - } - - // related https://app.shortcut.com/chainlinklabs/story/38295/creating-an-evm-chain-via-cli-or-api-immediately-polling-the-nodes-and-returning-an-error - // node must work and reconnect even if network is not working - time.Sleep(90 * time.Second) - activeEVMNetwork = networks.SimulatedEVMNonDev - netCfg := fmt.Sprintf(networkDRTOML, EVMFinalityDepth, EVMTrackerHistoryDepth) - chainlinkDeployment := chainlink.New(0, map[string]interface{}{ - "replicas": 1, - "toml": networks.AddNetworkDetailedConfig(baseDRTOML, netCfg, activeEVMNetwork), - }) - - err = testEnvironment.AddHelm(chainlinkDeployment).Run() - require.NoError(t, err, "Error adding to test environment") - - chainClient, err := blockchain.NewEVMClient(networkSettings, testEnvironment, l) - require.NoError(t, err, "Error connecting to blockchain") - cd, err := contracts.NewContractDeployer(chainClient, l) - require.NoError(t, err, "Error building contract deployer") - chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) - require.NoError(t, err, "Error connecting to Chainlink nodes") - ms, err := ctfClient.ConnectMockServer(testEnvironment) - require.NoError(t, err, "Error connecting to Mockserver") - - t.Cleanup(func() { - CleanupReorgTest(t, testEnvironment, chainlinkNodes, chainClient) - }) - - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, big.NewFloat(10)) - require.NoError(t, err, "Error funding Chainlink nodes") - - lt, err := cd.DeployLinkTokenContract() - require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") - oracle, err := cd.DeployOracle(lt.Address()) - require.NoError(t, err, "Deploying Oracle Contract shouldn't fail") - consumer, err := cd.DeployAPIConsumer(lt.Address()) - require.NoError(t, err, "Deploying Consumer Contract shouldn't fail") - err = chainClient.SetDefaultWallet(0) - require.NoError(t, err, "Setting default wallet shouldn't fail") - err = lt.Transfer(consumer.Address(), big.NewInt(2e18)) - require.NoError(t, err, "Transferring %d to consumer contract shouldn't fail", big.NewInt(2e18)) - - err = ms.SetValuePath("/variable", 5) - require.NoError(t, err, "Setting mockserver value path shouldn't fail") - - jobUUID := uuid.New() - - bta := client.BridgeTypeAttributes{ - Name: fmt.Sprintf("five-%s", jobUUID.String()), - URL: fmt.Sprintf("%s/variable", ms.Config.ClusterURL), - } - err = chainlinkNodes[0].MustCreateBridge(&bta) - require.NoError(t, err, "Creating bridge shouldn't fail") - - drps := &client.DirectRequestTxPipelineSpec{ - BridgeTypeAttributes: bta, - DataPath: "data,result", - } - ost, err := drps.String() - require.NoError(t, err, "Building observation source spec shouldn't fail") - - _, err = chainlinkNodes[0].MustCreateJob(&client.DirectRequestJobSpec{ - Name: "direct_request", - MinIncomingConfirmations: minIncomingConfirmations, - ContractAddress: oracle.Address(), - EVMChainID: chainClient.GetChainID().String(), - ExternalJobID: jobUUID.String(), - ObservationSource: ost, - }) - require.NoError(t, err, "Creating direct_request job shouldn't fail") - - rc, err := NewReorgController( - &ReorgConfig{ - FromPodLabel: reorg.TXNodesAppLabel, - ToPodLabel: reorg.MinerNodesAppLabel, - Network: chainClient, - Env: testEnvironment, - BlockConsensusThreshold: 3, - Timeout: 1800 * time.Second, - }, - ) - require.NoError(t, err, "Error getting reorg controller") - rc.ReOrg(reorgBlocks) - rc.WaitReorgStarted() - - jobUUIDReplaces := strings.Replace(jobUUID.String(), "-", "", 4) - var jobID [32]byte - copy(jobID[:], jobUUIDReplaces) - err = consumer.CreateRequestTo( - oracle.Address(), - jobID, - big.NewInt(1e18), - fmt.Sprintf("%s/variable", ms.Config.ClusterURL), - "data,result", - big.NewInt(100), - ) - require.NoError(t, err, "Calling oracle contract shouldn't fail") - - err = rc.WaitDepthReached() - require.NoError(t, err, "Error waiting for depth to be reached") - - gom := gomega.NewGomegaWithT(t) - gom.Eventually(func(g gomega.Gomega) { - d, err := consumer.Data(testcontext.Get(t)) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting data from consumer contract shouldn't fail") - g.Expect(d).ShouldNot(gomega.BeNil(), "Expected the initial on chain data to be nil") - log.Debug().Int64("Data", d.Int64()).Msg("Found on chain") - g.Expect(d.Int64()).Should(gomega.BeNumerically("==", 5), "Expected the on-chain data to be 5, but found %d", d.Int64()) - }, timeout, interval).Should(gomega.Succeed()) -} diff --git a/integration-tests/scripts/buildTests b/integration-tests/scripts/buildTests index edf4043ce1c..749bb545110 100755 --- a/integration-tests/scripts/buildTests +++ b/integration-tests/scripts/buildTests @@ -21,6 +21,6 @@ OIFS=$IFS IFS=' ' for x in $tosplit do - go test -c ./"${x}" + go test -c -tags embed ./"${x}" done IFS=$OIFS diff --git a/integration-tests/smoke/README.md b/integration-tests/smoke/README.md index 1dedc4e3840..266720c7bc6 100644 --- a/integration-tests/smoke/README.md +++ b/integration-tests/smoke/README.md @@ -52,18 +52,32 @@ Here is an example for 3 nodes cluster ``` ### Running against Live Testnets +1. Prepare your `overrides.toml` file with selected network and CL image name and version and save anywhere inside `integration-tests` folder. +```toml +[ChainlinkImage] +image="your-image" +version="your-version" +[Network] +selected_networks=["polygon_mumbai"] + +[Network.RpcHttpUrls] +polygon_mumbai=["https://http.endpoint.com"] + +[Network.RpcWsUrls] +polygon_mumbai=["wss://ws.endpoint.com"] + +[Network.WalletKeys] +polygon_mumbai=["my_so_private_key"] ``` -SELECTED_NETWORKS= \ -_KEYS= \ -_URLS= \ -_HTTP_URLS= \ +Then execute: +```bash go test -v -run ${TestName} ``` ### Debugging CL client API calls -``` +```bash export CL_CLIENT_DEBUG=true ``` \ No newline at end of file diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 0bdb6cf1f4e..3f69e7f829c 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -17,8 +17,8 @@ import ( ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" - - "github.com/kelseyhightower/envconfig" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + "github.com/smartcontractkit/chainlink/integration-tests/types" "github.com/ethereum/go-ethereum/common" "github.com/onsi/gomega" @@ -68,18 +68,27 @@ var ( func TestMain(m *testing.M) { logging.Init() - fmt.Printf("Running Smoke Test on %s\n", networks.MustGetSelectedNetworksFromEnv()[0].Name) // Print to get around disabled logging - fmt.Printf("Chainlink Image %s\n", os.Getenv("CHAINLINK_IMAGE")) // Print to get around disabled logging - fmt.Printf("Chainlink Version %s\n", os.Getenv("CHAINLINK_VERSION")) // Print to get around disabled logging + // config, err := tc.GetConfig(tc.NoTest, tc.Smoke, tc.Automation) + // if err != nil { + // panic(err) + // } + // fmt.Printf("Running Smoke Test on %s\n", networks.MustGetSelectedNetworkConfig(config.Network)[0].Name) // Print to get around disabled logging + // fmt.Printf("Chainlink Image %v\n", config.ChainlinkImage.Image) // Print to get around disabled logging + // fmt.Printf("Chainlink Version %v\n", config.ChainlinkImage.Version) // Print to get around disabled logging os.Exit(m.Run()) } func TestAutomationBasic(t *testing.T) { - SetupAutomationBasic(t, false) + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } + SetupAutomationBasic(t, false, &config) } -func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { +func SetupAutomationBasic(t *testing.T, nodeUpgrade bool, automationTestConfig types.AutomationTestConfig) { t.Parallel() + registryVersions := map[string]ethereum.KeeperRegistryVersion{ "registry_2_0": ethereum.RegistryVersion_2_0, "registry_2_1_conditional": ethereum.RegistryVersion_2_1, @@ -93,19 +102,14 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { name := name registryVersion := registryVersion t.Run(name, func(t *testing.T) { + cfg := tc.MustCopy(automationTestConfig) t.Parallel() l := logging.GetTestLogger(t) - var ( - upgradeImage string - upgradeVersion string - err error - ) + var err error if nodeUpgrade { - upgradeImage = os.Getenv("UPGRADE_IMAGE") - upgradeVersion = os.Getenv("UPGRADE_VERSION") - if len(upgradeImage) == 0 || len(upgradeVersion) == 0 { - t.Fatal("UPGRADE_IMAGE and UPGRADE_VERSION must be set to upgrade nodes") + if cfg.GetChainlinkUpgradeImageConfig() == nil { + t.Fatal("[ChainlinkUpgradeImage] must be set in TOML config to upgrade nodes") } } @@ -116,7 +120,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { isMercury := isMercuryV02 || isMercuryV03 a := setupAutomationTestDocker( - t, registryVersion, automationDefaultRegistryConfig, isMercuryV02, isMercuryV03, + t, registryVersion, automationDefaultRegistryConfig, isMercuryV02, isMercuryV03, automationTestConfig, ) consumers, upkeepIDs := actions.DeployConsumers( @@ -172,10 +176,11 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { l.Info().Msgf("Total time taken to get 5 performs for each upkeep: %s", time.Since(startTime)) if nodeUpgrade { + require.NotNil(t, cfg.GetChainlinkImageConfig(), "unable to upgrade node version, [ChainlinkUpgradeImage] was not set, must both a new image or a new version") expect := 5 // Upgrade the nodes one at a time and check that the upkeeps are still being performed for i := 0; i < 5; i++ { - err = actions.UpgradeChainlinkNodeVersionsLocal(upgradeImage, upgradeVersion, a.DockerEnv.ClCluster.Nodes[i]) + err = actions.UpgradeChainlinkNodeVersionsLocal(*cfg.GetChainlinkImageConfig().Image, *cfg.GetChainlinkImageConfig().Version, a.DockerEnv.ClCluster.Nodes[i]) require.NoError(t, err, "Error when upgrading node %d", i) time.Sleep(time.Second * 10) expect = expect + 5 @@ -229,8 +234,13 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } + a := setupAutomationTestDocker( - t, ethereum.RegistryVersion_2_1, automationDefaultRegistryConfig, false, false, + t, ethereum.RegistryVersion_2_1, automationDefaultRegistryConfig, false, false, &config, ) consumers, upkeepIDs := actions.DeployConsumers( @@ -308,7 +318,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { require.NoError(t, err, "Could not set upkeep trigger config at index %d", i) } - err := a.ChainClient.WaitForEvents() + err = a.ChainClient.WaitForEvents() require.NoError(t, err, "Error encountered when waiting for setting trigger config for upkeeps") var countersAfterSetNoMatch = make([]*big.Int, len(upkeepIDs)) @@ -404,8 +414,12 @@ func TestAutomationAddFunds(t *testing.T) { registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } a := setupAutomationTestDocker( - t, registryVersion, automationDefaultRegistryConfig, false, false, + t, registryVersion, automationDefaultRegistryConfig, false, false, &config, ) consumers, upkeepIDs := actions.DeployConsumers( @@ -432,7 +446,7 @@ func TestAutomationAddFunds(t *testing.T) { }, "2m", "1s").Should(gomega.Succeed()) // ~1m for setup, 1m assertion // Grant permission to the registry to fund the upkeep - err := a.LinkToken.Approve(a.Registry.Address(), big.NewInt(9e18)) + err = a.LinkToken.Approve(a.Registry.Address(), big.NewInt(9e18)) require.NoError(t, err, "Could not approve permissions for the registry on the link token contract") err = a.ChainClient.WaitForEvents() require.NoError(t, err, "Error waiting for events") @@ -467,8 +481,12 @@ func TestAutomationPauseUnPause(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } a := setupAutomationTestDocker( - t, registryVersion, automationDefaultRegistryConfig, false, false, + t, registryVersion, automationDefaultRegistryConfig, false, false, &config, ) consumers, upkeepIDs := actions.DeployConsumers( @@ -503,7 +521,7 @@ func TestAutomationPauseUnPause(t *testing.T) { require.NoError(t, err, "Could not pause upkeep at index %d", i) } - err := a.ChainClient.WaitForEvents() + err = a.ChainClient.WaitForEvents() require.NoError(t, err, "Error waiting for upkeeps to be paused") var countersAfterPause = make([]*big.Int, len(upkeepIDs)) @@ -562,8 +580,12 @@ func TestAutomationRegisterUpkeep(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } a := setupAutomationTestDocker( - t, registryVersion, automationDefaultRegistryConfig, false, false, + t, registryVersion, automationDefaultRegistryConfig, false, false, &config, ) consumers, upkeepIDs := actions.DeployConsumers( @@ -645,8 +667,12 @@ func TestAutomationPauseRegistry(t *testing.T) { registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } a := setupAutomationTestDocker( - t, registryVersion, automationDefaultRegistryConfig, false, false, + t, registryVersion, automationDefaultRegistryConfig, false, false, &config, ) consumers, upkeepIDs := actions.DeployConsumers( @@ -675,7 +701,7 @@ func TestAutomationPauseRegistry(t *testing.T) { }, "4m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~1m for performing each upkeep once, ~2m buffer // Pause the registry - err := a.Registry.Pause() + err = a.Registry.Pause() require.NoError(t, err, "Error pausing registry") err = a.ChainClient.WaitForEvents() require.NoError(t, err, "Error waiting for registry to pause") @@ -715,8 +741,12 @@ func TestAutomationKeeperNodesDown(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } a := setupAutomationTestDocker( - t, registryVersion, automationDefaultRegistryConfig, false, false, + t, registryVersion, automationDefaultRegistryConfig, false, false, &config, ) consumers, upkeepIDs := actions.DeployConsumers( @@ -750,7 +780,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) { }, "4m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~1m for performing each upkeep once, ~2m buffer // Take down 1 node. Currently, using 4 nodes so f=1 and is the max nodes that can go down. - err := nodesWithoutBootstrap[0].MustDeleteJob("1") + err = nodesWithoutBootstrap[0].MustDeleteJob("1") require.NoError(t, err, "Error deleting job from Chainlink node") err = a.ChainClient.WaitForEvents() require.NoError(t, err, "Error waiting for blockchain events") @@ -814,8 +844,12 @@ func TestAutomationPerformSimulation(t *testing.T) { registryVersion := registryVersion t.Run(name, func(t *testing.T) { t.Parallel() + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } a := setupAutomationTestDocker( - t, registryVersion, automationDefaultRegistryConfig, false, false, + t, registryVersion, automationDefaultRegistryConfig, false, false, &config, ) consumersPerformance, _ := actions.DeployPerformanceConsumers( @@ -848,7 +882,7 @@ func TestAutomationPerformSimulation(t *testing.T) { }, "2m", "1s").Should(gomega.Succeed()) // ~1m for setup, 1m assertion // Set performGas on consumer to be low, so that performUpkeep starts becoming successful - err := consumerPerformance.SetPerformGasToBurn(testcontext.Get(t), big.NewInt(100000)) + err = consumerPerformance.SetPerformGasToBurn(testcontext.Get(t), big.NewInt(100000)) require.NoError(t, err, "Perform gas should be set successfully on consumer") err = a.ChainClient.WaitForEvents() require.NoError(t, err, "Error waiting for set perform gas tx") @@ -878,8 +912,12 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } a := setupAutomationTestDocker( - t, registryVersion, automationDefaultRegistryConfig, false, false, + t, registryVersion, automationDefaultRegistryConfig, false, false, &config, ) consumersPerformance, upkeepIDs := actions.DeployPerformanceConsumers( @@ -914,7 +952,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { }, "2m", "1s").Should(gomega.Succeed()) // ~1m for setup, 1m assertion // Increase gas limit for the upkeep, higher than the performGasBurn - err := a.Registry.SetUpkeepGasLimit(upkeepID, uint32(4500000)) + err = a.Registry.SetUpkeepGasLimit(upkeepID, uint32(4500000)) require.NoError(t, err, "Error setting upkeep gas limit") err = a.ChainClient.WaitForEvents() require.NoError(t, err, "Error waiting for SetUpkeepGasLimit tx") @@ -992,8 +1030,13 @@ func TestUpdateCheckData(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.Automation) + if err != nil { + t.Fatal(err) + } + a := setupAutomationTestDocker( - t, registryVersion, automationDefaultRegistryConfig, false, false, + t, registryVersion, automationDefaultRegistryConfig, false, false, &config, ) performDataChecker, upkeepIDs := actions.DeployPerformDataCheckerConsumers( @@ -1027,7 +1070,7 @@ func TestUpdateCheckData(t *testing.T) { require.NoError(t, err, "Could not update check data for upkeep at index %d", i) } - err := a.ChainClient.WaitForEvents() + err = a.ChainClient.WaitForEvents() require.NoError(t, err, "Error while waiting for check data update") // retrieve new check data for all upkeeps @@ -1052,23 +1095,20 @@ func TestUpdateCheckData(t *testing.T) { } } -type TestConfig struct { - ChainlinkNodeFunding float64 `envconfig:"CHAINLINK_NODE_FUNDING" default:"1"` -} - func setupAutomationTestDocker( t *testing.T, registryVersion ethereum.KeeperRegistryVersion, registryConfig contracts.KeeperRegistrySettings, isMercuryV02 bool, isMercuryV03 bool, + automationTestConfig types.AutomationTestConfig, ) automationv2.AutomationTest { require.False(t, isMercuryV02 && isMercuryV03, "Cannot run test with both Mercury V02 and V03 on") l := logging.GetTestLogger(t) // Add registry version to config registryConfig.RegistryVersion = registryVersion - network := networks.MustGetSelectedNetworksFromEnv()[0] + network := networks.MustGetSelectedNetworkConfig(automationTestConfig.GetNetworkConfig())[0] // build the node config clNodeConfig := node.NewConfig(node.NewBaseConfig()) @@ -1084,17 +1124,16 @@ func setupAutomationTestDocker( //launch the environment var env *test_env.CLClusterTestEnv var err error - var testConfig TestConfig - err = envconfig.Process("AUTOMATION", &testConfig) require.NoError(t, err) - l.Debug().Msgf("Funding amount: %f", testConfig.ChainlinkNodeFunding) + l.Debug().Msgf("Funding amount: %f", *automationTestConfig.GetCommonConfig().ChainlinkNodeFunding) clNodesCount := 5 if isMercuryV02 || isMercuryV03 { env, err = test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(automationTestConfig). WithGeth(). WithMockAdapter(). - WithFunding(big.NewFloat(testConfig.ChainlinkNodeFunding)). + WithFunding(big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)). WithStandardCleanup(). Build() require.NoError(t, err, "Error deploying test environment for Mercury") @@ -1120,19 +1159,20 @@ func setupAutomationTestDocker( node.SetChainConfig(clNodeConfig, wsUrls, httpUrls, network, false) - err = env.StartClCluster(clNodeConfig, clNodesCount, secretsConfig) + err = env.StartClCluster(clNodeConfig, clNodesCount, secretsConfig, automationTestConfig) require.NoError(t, err, "Error starting CL nodes test environment for Mercury") - err = env.FundChainlinkNodes(big.NewFloat(testConfig.ChainlinkNodeFunding)) + err = env.FundChainlinkNodes(big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)) require.NoError(t, err, "Error funding CL nodes") } else { env, err = test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(automationTestConfig). WithGeth(). WithMockAdapter(). WithCLNodes(clNodesCount). WithCLNodeConfig(clNodeConfig). - WithFunding(big.NewFloat(testConfig.ChainlinkNodeFunding)). + WithFunding(big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)). WithStandardCleanup(). Build() require.NoError(t, err, "Error deploying test environment") diff --git a/integration-tests/smoke/automation_upgrade_test.go b/integration-tests/smoke/automation_upgrade_test.go index 28285543621..6601457de8b 100644 --- a/integration-tests/smoke/automation_upgrade_test.go +++ b/integration-tests/smoke/automation_upgrade_test.go @@ -2,8 +2,14 @@ package smoke import ( "testing" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestAutomationNodeUpgrade(t *testing.T) { - SetupAutomationBasic(t, true) + config, err := tc.GetConfig(t.Name(), tc.Automation) + if err != nil { + t.Fatal(err, "Error getting config") + } + SetupAutomationBasic(t, true, &config) } diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index df1b85882e9..b6e04612aca 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -13,14 +13,21 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestCronBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.Cron) + if err != nil { + t.Fatal(err) + } + env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithGeth(). WithMockAdapter(). WithCLNodes(1). @@ -65,8 +72,14 @@ func TestCronJobReplacement(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.Cron) + if err != nil { + t.Fatal(err) + } + env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithGeth(). WithMockAdapter(). WithCLNodes(1). diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index 345971e8922..c8cec4e385b 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -19,14 +19,21 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestFluxBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.Flux) + if err != nil { + t.Fatal(err) + } + env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithGeth(). WithMockAdapter(). WithCLNodes(3). diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index fd8dfc780af..5c603c5b08f 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -12,14 +12,21 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestForwarderOCRBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.ForwarderOcr) + if err != nil { + t.Fatal(err) + } + env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithGeth(). WithMockAdapter(). WithForwarders(). diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index f1a01643f5e..9385fb4f9a5 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -17,14 +17,22 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestForwarderOCR2Basic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.ForwarderOcr2) + if err != nil { + t.Fatal(err) + } + env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithGeth(). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index cac5aa93d36..0ebbc1e083d 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -22,6 +22,8 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) const ( @@ -86,7 +88,12 @@ func TestKeeperBasicSmoke(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, @@ -100,7 +107,7 @@ func TestKeeperBasicSmoke(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -162,7 +169,12 @@ func TestKeeperBlockCountPerTurn(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, @@ -176,7 +188,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -266,7 +278,12 @@ func TestKeeperSimulation(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumersPerformance, upkeepIDs := actions.DeployPerformanceKeeperContracts( t, registryVersion, @@ -284,7 +301,7 @@ func TestKeeperSimulation(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -339,7 +356,11 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumersPerformance, upkeepIDs := actions.DeployPerformanceKeeperContracts( t, registryVersion, @@ -357,7 +378,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -452,7 +473,11 @@ func TestKeeperRegisterUpkeep(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, registrar, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, @@ -466,7 +491,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -541,7 +566,11 @@ func TestKeeperAddFunds(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, @@ -555,7 +584,7 @@ func TestKeeperAddFunds(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -604,7 +633,11 @@ func TestKeeperRemove(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, @@ -618,7 +651,7 @@ func TestKeeperRemove(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -682,7 +715,11 @@ func TestKeeperPauseRegistry(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, @@ -696,7 +733,7 @@ func TestKeeperPauseRegistry(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -743,7 +780,11 @@ func TestKeeperPauseRegistry(t *testing.T) { func TestKeeperMigrateRegistry(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, ethereum.RegistryVersion_1_2, @@ -757,7 +798,7 @@ func TestKeeperMigrateRegistry(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -835,7 +876,11 @@ func TestKeeperNodeDown(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, @@ -941,7 +986,11 @@ type nodeAndJob struct { func TestKeeperPauseUnPauseUpkeep(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, ethereum.RegistryVersion_1_3, @@ -955,7 +1004,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -1031,7 +1080,11 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) { func TestKeeperUpdateCheckData(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, performDataChecker, upkeepIDs := actions.DeployPerformDataCheckerContracts( t, ethereum.RegistryVersion_1_3, @@ -1046,7 +1099,7 @@ func TestKeeperUpdateCheckData(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -1090,7 +1143,7 @@ func TestKeeperUpdateCheckData(t *testing.T) { }, "3m", "1s").Should(gomega.Succeed()) } -func setupKeeperTest(t *testing.T) ( +func setupKeeperTest(t *testing.T, config *tc.TestConfig) ( blockchain.EVMClient, []*client.ChainlinkClient, contracts.ContractDeployer, @@ -1107,6 +1160,7 @@ func setupKeeperTest(t *testing.T) ( env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(config). WithGeth(). WithCLNodes(5). WithCLNodeConfig(clNodeConfig). @@ -1128,10 +1182,14 @@ func setupKeeperTest(t *testing.T) ( func TestKeeperJobReplacement(t *testing.T) { t.Parallel() + l := logging.GetTestLogger(t) registryVersion := ethereum.RegistryVersion_1_3 + config, err := tc.GetConfig("Smoke", tc.Keeper) + if err != nil { + t.Fatal(err) + } - l := logging.GetTestLogger(t) - chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t) + chainClient, chainlinkNodes, contractDeployer, linkToken, _ := setupKeeperTest(t, &config) registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, @@ -1145,7 +1203,7 @@ func TestKeeperJobReplacement(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) + _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go index 4eadf6b3913..593b4eb879a 100644 --- a/integration-tests/smoke/log_poller_test.go +++ b/integration-tests/smoke/log_poller_test.go @@ -17,6 +17,8 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + lp_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/log_poller" logpoller "github.com/smartcontractkit/chainlink/integration-tests/universal/log_poller" core_logger "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -25,262 +27,42 @@ import ( // consistency test with no network disruptions with approximate emission of 1500-1600 logs per second for ~110-120 seconds // 6 filters are registered func TestLogPollerFewFiltersFixedDepth(t *testing.T) { - cfg := logpoller.Config{ - General: &logpoller.General{ - Generator: logpoller.GeneratorType_Looped, - Contracts: 2, - EventsPerTx: 4, - UseFinalityTag: false, - }, - LoopedConfig: &logpoller.LoopedConfig{ - ContractConfig: logpoller.ContractConfig{ - ExecutionCount: 100, - }, - FuzzConfig: logpoller.FuzzConfig{ - MinEmitWaitTimeMs: 200, - MaxEmitWaitTimeMs: 500, - }, - }, - } - - eventsToEmit := []abi.Event{} - for _, event := range logpoller.EmitterABI.Events { - eventsToEmit = append(eventsToEmit, event) - } - - cfg.General.EventsToEmit = eventsToEmit - - // this was added only to support triggering tests from CI with custom values - err := cfg.OverrideFromEnv() - require.NoError(t, err, fmt.Sprintf("Error overriding config from env: %v", err)) - - executeBasicLogPollerTest(t, &cfg) + executeBasicLogPollerTest(t) } func TestLogPollerFewFiltersFinalityTag(t *testing.T) { - cfg := logpoller.Config{ - General: &logpoller.General{ - Generator: logpoller.GeneratorType_Looped, - Contracts: 2, - EventsPerTx: 4, - UseFinalityTag: true, - }, - LoopedConfig: &logpoller.LoopedConfig{ - ContractConfig: logpoller.ContractConfig{ - ExecutionCount: 100, - }, - FuzzConfig: logpoller.FuzzConfig{ - MinEmitWaitTimeMs: 200, - MaxEmitWaitTimeMs: 500, - }, - }, - } - - eventsToEmit := []abi.Event{} - for _, event := range logpoller.EmitterABI.Events { - eventsToEmit = append(eventsToEmit, event) - } - - cfg.General.EventsToEmit = eventsToEmit - - executeBasicLogPollerTest(t, &cfg) + executeBasicLogPollerTest(t) } // consistency test with no network disruptions with approximate emission of 1000-1100 logs per second for ~110-120 seconds // 900 filters are registered func TestLogPollerManyFiltersFixedDepth(t *testing.T) { t.Skip("Execute manually, when needed as it runs for a long time") - cfg := logpoller.Config{ - General: &logpoller.General{ - Generator: logpoller.GeneratorType_Looped, - Contracts: 300, - EventsPerTx: 3, - UseFinalityTag: false, - }, - LoopedConfig: &logpoller.LoopedConfig{ - ContractConfig: logpoller.ContractConfig{ - ExecutionCount: 30, - }, - FuzzConfig: logpoller.FuzzConfig{ - MinEmitWaitTimeMs: 200, - MaxEmitWaitTimeMs: 500, - }, - }, - } - - eventsToEmit := []abi.Event{} - for _, event := range logpoller.EmitterABI.Events { - eventsToEmit = append(eventsToEmit, event) - } - - cfg.General.EventsToEmit = eventsToEmit - - executeBasicLogPollerTest(t, &cfg) + executeBasicLogPollerTest(t) } func TestLogPollerManyFiltersFinalityTag(t *testing.T) { t.Skip("Execute manually, when needed as it runs for a long time") - cfg := logpoller.Config{ - General: &logpoller.General{ - Generator: logpoller.GeneratorType_Looped, - Contracts: 300, - EventsPerTx: 3, - UseFinalityTag: true, - }, - LoopedConfig: &logpoller.LoopedConfig{ - ContractConfig: logpoller.ContractConfig{ - ExecutionCount: 30, - }, - FuzzConfig: logpoller.FuzzConfig{ - MinEmitWaitTimeMs: 200, - MaxEmitWaitTimeMs: 500, - }, - }, - } - - eventsToEmit := []abi.Event{} - for _, event := range logpoller.EmitterABI.Events { - eventsToEmit = append(eventsToEmit, event) - } - - cfg.General.EventsToEmit = eventsToEmit - - executeBasicLogPollerTest(t, &cfg) + executeBasicLogPollerTest(t) } // consistency test that introduces random distruptions by pausing either Chainlink or Postgres containers for random interval of 5-20 seconds // with approximate emission of 520-550 logs per second for ~110 seconds // 6 filters are registered func TestLogPollerWithChaosFixedDepth(t *testing.T) { - cfg := logpoller.Config{ - General: &logpoller.General{ - Generator: logpoller.GeneratorType_Looped, - Contracts: 2, - EventsPerTx: 100, - UseFinalityTag: false, - }, - LoopedConfig: &logpoller.LoopedConfig{ - ContractConfig: logpoller.ContractConfig{ - ExecutionCount: 70, - }, - FuzzConfig: logpoller.FuzzConfig{ - MinEmitWaitTimeMs: 100, - MaxEmitWaitTimeMs: 300, - }, - }, - ChaosConfig: &logpoller.ChaosConfig{ - ExperimentCount: 4, - TargetComponent: "chainlink", - }, - } - - eventsToEmit := []abi.Event{} - for _, event := range logpoller.EmitterABI.Events { - eventsToEmit = append(eventsToEmit, event) - } - - cfg.General.EventsToEmit = eventsToEmit - - executeBasicLogPollerTest(t, &cfg) + executeBasicLogPollerTest(t) } func TestLogPollerWithChaosFinalityTag(t *testing.T) { - cfg := logpoller.Config{ - General: &logpoller.General{ - Generator: logpoller.GeneratorType_Looped, - Contracts: 2, - EventsPerTx: 100, - UseFinalityTag: true, - }, - LoopedConfig: &logpoller.LoopedConfig{ - ContractConfig: logpoller.ContractConfig{ - ExecutionCount: 120, - }, - FuzzConfig: logpoller.FuzzConfig{ - MinEmitWaitTimeMs: 100, - MaxEmitWaitTimeMs: 300, - }, - }, - ChaosConfig: &logpoller.ChaosConfig{ - ExperimentCount: 6, - TargetComponent: "chainlink", - }, - } - - eventsToEmit := []abi.Event{} - for _, event := range logpoller.EmitterABI.Events { - eventsToEmit = append(eventsToEmit, event) - } - - cfg.General.EventsToEmit = eventsToEmit - - executeBasicLogPollerTest(t, &cfg) -} - -func TestLogPollerWithChaosPostgresFinalityTag(t *testing.T) { - cfg := logpoller.Config{ - General: &logpoller.General{ - Generator: logpoller.GeneratorType_Looped, - Contracts: 2, - EventsPerTx: 100, - UseFinalityTag: true, - }, - LoopedConfig: &logpoller.LoopedConfig{ - ContractConfig: logpoller.ContractConfig{ - ExecutionCount: 120, - }, - FuzzConfig: logpoller.FuzzConfig{ - MinEmitWaitTimeMs: 100, - MaxEmitWaitTimeMs: 300, - }, - }, - ChaosConfig: &logpoller.ChaosConfig{ - ExperimentCount: 6, - TargetComponent: "postgres", - }, - } - - eventsToEmit := []abi.Event{} - for _, event := range logpoller.EmitterABI.Events { - eventsToEmit = append(eventsToEmit, event) - } - - cfg.General.EventsToEmit = eventsToEmit - - executeBasicLogPollerTest(t, &cfg) + executeBasicLogPollerTest(t) } func TestLogPollerWithChaosPostgresFixedDepth(t *testing.T) { - cfg := logpoller.Config{ - General: &logpoller.General{ - Generator: logpoller.GeneratorType_Looped, - Contracts: 2, - EventsPerTx: 100, - UseFinalityTag: false, - }, - LoopedConfig: &logpoller.LoopedConfig{ - ContractConfig: logpoller.ContractConfig{ - ExecutionCount: 120, - }, - FuzzConfig: logpoller.FuzzConfig{ - MinEmitWaitTimeMs: 100, - MaxEmitWaitTimeMs: 300, - }, - }, - ChaosConfig: &logpoller.ChaosConfig{ - ExperimentCount: 6, - TargetComponent: "postgres", - }, - } - - eventsToEmit := []abi.Event{} - for _, event := range logpoller.EmitterABI.Events { - eventsToEmit = append(eventsToEmit, event) - } - - cfg.General.EventsToEmit = eventsToEmit + executeBasicLogPollerTest(t) +} - executeBasicLogPollerTest(t, &cfg) +func TestLogPollerWithChaosPostgresFinalityTag(t *testing.T) { + executeBasicLogPollerTest(t) } // consistency test that registers filters after events were emitted and then triggers replay via API @@ -289,72 +71,31 @@ func TestLogPollerWithChaosPostgresFixedDepth(t *testing.T) { // with approximate emission of 24 logs per second for ~110 seconds // 6 filters are registered func TestLogPollerReplayFixedDepth(t *testing.T) { - cfg := logpoller.Config{ - General: &logpoller.General{ - Generator: logpoller.GeneratorType_Looped, - Contracts: 2, - EventsPerTx: 4, - UseFinalityTag: false, - }, - LoopedConfig: &logpoller.LoopedConfig{ - ContractConfig: logpoller.ContractConfig{ - ExecutionCount: 100, - }, - FuzzConfig: logpoller.FuzzConfig{ - MinEmitWaitTimeMs: 200, - MaxEmitWaitTimeMs: 500, - }, - }, - } - - eventsToEmit := []abi.Event{} - for _, event := range logpoller.EmitterABI.Events { - eventsToEmit = append(eventsToEmit, event) - } - - cfg.General.EventsToEmit = eventsToEmit - consistencyTimeout := "5m" - - executeLogPollerReplay(t, &cfg, consistencyTimeout) + executeLogPollerReplay(t, "5m") } func TestLogPollerReplayFinalityTag(t *testing.T) { - cfg := logpoller.Config{ - General: &logpoller.General{ - Generator: logpoller.GeneratorType_Looped, - Contracts: 2, - EventsPerTx: 4, - UseFinalityTag: true, - }, - LoopedConfig: &logpoller.LoopedConfig{ - ContractConfig: logpoller.ContractConfig{ - ExecutionCount: 100, - }, - FuzzConfig: logpoller.FuzzConfig{ - MinEmitWaitTimeMs: 200, - MaxEmitWaitTimeMs: 500, - }, - }, - } + executeLogPollerReplay(t, "5m") +} + +// HELPER FUNCTIONS +func executeBasicLogPollerTest(t *testing.T) { + testConfig, err := tc.GetConfig(t.Name(), tc.LogPoller) + require.NoError(t, err, "Error getting config") eventsToEmit := []abi.Event{} for _, event := range logpoller.EmitterABI.Events { eventsToEmit = append(eventsToEmit, event) } + cfg := testConfig.LogPoller cfg.General.EventsToEmit = eventsToEmit - consistencyTimeout := "5m" - executeLogPollerReplay(t, &cfg, consistencyTimeout) -} - -func executeBasicLogPollerTest(t *testing.T, cfg *logpoller.Config) { l := logging.GetTestLogger(t) coreLogger := core_logger.TestLogger(t) //needed by ORM ¯\_(ツ)_/¯ - lpTestEnv := prepareEnvironment(l, t, cfg) + lpTestEnv := prepareEnvironment(l, t, &testConfig) testEnv := lpTestEnv.testEnv - var err error // Register log triggered upkeep for each combination of log emitter contract and event signature (topic) // We need to register a separate upkeep for each event signature, because log trigger doesn't support multiple topics (even if log poller does) @@ -417,13 +158,23 @@ func executeBasicLogPollerTest(t *testing.T, cfg *logpoller.Config) { conditionallyWaitUntilNodesHaveTheSameLogsAsEvm(l, coreLogger, t, allNodesLogCountMatches, lpTestEnv, cfg, startBlock, endBlock, "5m") } -func executeLogPollerReplay(t *testing.T, cfg *logpoller.Config, consistencyTimeout string) { +func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { + testConfig, err := tc.GetConfig(t.Name(), tc.LogPoller) + require.NoError(t, err, "Error getting config") + + eventsToEmit := []abi.Event{} + for _, event := range logpoller.EmitterABI.Events { + eventsToEmit = append(eventsToEmit, event) + } + + cfg := testConfig.LogPoller + cfg.General.EventsToEmit = eventsToEmit + l := logging.GetTestLogger(t) coreLogger := core_logger.TestLogger(t) //needed by ORM ¯\_(ツ)_/¯ - lpTestEnv := prepareEnvironment(l, t, cfg) + lpTestEnv := prepareEnvironment(l, t, &testConfig) testEnv := lpTestEnv.testEnv - var err error // Save block number before starting to emit events, so that we can later use it when querying logs sb, err := testEnv.EVMClient.LatestBlockNumber(testcontext.Get(t)) @@ -505,7 +256,8 @@ type logPollerEnvironment struct { // prepareEnvironment prepares environment for log poller tests by starting DON, private Ethereum network, // deploying registry and log emitter contracts and registering log triggered upkeeps -func prepareEnvironment(l zerolog.Logger, t *testing.T, cfg *logpoller.Config) logPollerEnvironment { +func prepareEnvironment(l zerolog.Logger, t *testing.T, testConfig *tc.TestConfig) logPollerEnvironment { + cfg := testConfig.LogPoller if cfg.General.EventsToEmit == nil || len(cfg.General.EventsToEmit) == 0 { l.Warn().Msg("No events to emit specified, using all events from log emitter contract") for _, event := range logpoller.EmitterABI.Events { @@ -517,11 +269,17 @@ func prepareEnvironment(l zerolog.Logger, t *testing.T, cfg *logpoller.Config) l var ( err error - upKeepsNeeded = cfg.General.Contracts * len(cfg.General.EventsToEmit) + upKeepsNeeded = *cfg.General.Contracts * len(cfg.General.EventsToEmit) ) chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := logpoller.SetupLogPollerTestDocker( - t, ethereum.RegistryVersion_2_1, logpoller.DefaultOCRRegistryConfig, upKeepsNeeded, time.Duration(500*time.Millisecond), cfg.General.UseFinalityTag, + t, + ethereum.RegistryVersion_2_1, + logpoller.DefaultOCRRegistryConfig, + upKeepsNeeded, + time.Duration(500*time.Millisecond), + *cfg.General.UseFinalityTag, + testConfig, ) _, upkeepIDs := actions.DeployConsumers( @@ -591,7 +349,7 @@ func waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(l zerolog.Logger, core // conditionallyWaitUntilNodesHaveTheSameLogsAsEvm checks whether all CL nodes have the same number of logs as EVM node // if not, then it prints missing logs and wait for some time and checks again -func conditionallyWaitUntilNodesHaveTheSameLogsAsEvm(l zerolog.Logger, coreLogger core_logger.SugaredLogger, t *testing.T, allNodesLogCountMatches bool, lpTestEnv logPollerEnvironment, cfg *logpoller.Config, startBlock, endBlock int64, waitDuration string) { +func conditionallyWaitUntilNodesHaveTheSameLogsAsEvm(l zerolog.Logger, coreLogger core_logger.SugaredLogger, t *testing.T, allNodesLogCountMatches bool, lpTestEnv logPollerEnvironment, cfg *lp_config.Config, startBlock, endBlock int64, waitDuration string) { logCountWaitDuration, err := time.ParseDuration(waitDuration) require.NoError(t, err, "Error parsing log count wait duration") diff --git a/integration-tests/smoke/log_poller_test.go_test_list.json b/integration-tests/smoke/log_poller_test.go_test_list.json index 5193c3fd06c..2159654e283 100644 --- a/integration-tests/smoke/log_poller_test.go_test_list.json +++ b/integration-tests/smoke/log_poller_test.go_test_list.json @@ -35,7 +35,7 @@ { "name": "TestLogPollerManyFiltersFixedDepth", "label": "ubuntu-latest" - }, + }, { "name": "TestLogPollerManyFiltersFinalityTag", "label": "ubuntu-latest" diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index f45c324faed..9e06ee527cd 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -11,12 +11,12 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" ) @@ -42,11 +42,17 @@ func TestOCRv2Basic(t *testing.T) { l := logging.GetTestLogger(t) - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + config, err := tc.GetConfig("Smoke", tc.OCR2) + if err != nil { + t.Fatal(err) + } + + network, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithPrivateEthereumNetwork(network). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), @@ -124,11 +130,17 @@ func TestOCRv2Request(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + config, err := tc.GetConfig("Smoke", tc.ForwarderOcr) + if err != nil { + t.Fatal(err) + } + + network, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithPrivateEthereumNetwork(network). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), @@ -202,8 +214,14 @@ func TestOCRv2Request(t *testing.T) { func TestOCRv2JobReplacement(t *testing.T) { l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.OCR2) + if err != nil { + t.Fatal(err) + } + env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithGeth(). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), diff --git a/integration-tests/smoke/ocr2vrf_test.go b/integration-tests/smoke/ocr2vrf_test.go index 773476826c7..c01ac46fbbc 100644 --- a/integration-tests/smoke/ocr2vrf_test.go +++ b/integration-tests/smoke/ocr2vrf_test.go @@ -10,6 +10,7 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" eth "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" @@ -23,12 +24,21 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) +var ocr2vrfSmokeConfig *testconfig.TestConfig + func TestOCR2VRFRedeemModel(t *testing.T) { t.Parallel() t.Skip("VRFv3 is on pause, skipping") l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.OCR2) + if err != nil { + t.Fatal(err) + } + testEnvironment, testNetwork := setupOCR2VRFEnvironment(t) if testEnvironment.WillUseRemoteRunner() { return @@ -44,7 +54,7 @@ func TestOCR2VRFRedeemModel(t *testing.T) { require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") t.Cleanup(func() { - err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, chainClient) + err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, &config, chainClient) require.NoError(t, err, "Error tearing down environment") }) @@ -91,6 +101,11 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { t.Parallel() t.Skip("VRFv3 is on pause, skipping") l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.OCR2) + if err != nil { + t.Fatal(err) + } + testEnvironment, testNetwork := setupOCR2VRFEnvironment(t) if testEnvironment.WillUseRemoteRunner() { return @@ -106,7 +121,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") t.Cleanup(func() { - err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, chainClient) + err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, &config, chainClient) require.NoError(t, err, "Error tearing down environment") }) @@ -149,7 +164,15 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { } func setupOCR2VRFEnvironment(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) { - testNetwork = networks.MustGetSelectedNetworksFromEnv()[0] + if ocr2vrfSmokeConfig == nil { + c, err := testconfig.GetConfig("Smoke", tc.OCR2VRF) + if err != nil { + t.Fatal(err) + } + ocr2vrfSmokeConfig = &c + } + + testNetwork = networks.MustGetSelectedNetworkConfig(ocr2vrfSmokeConfig.Network)[0] evmConfig := eth.New(nil) if !testNetwork.Simulated { evmConfig = eth.New(ð.Props{ @@ -159,14 +182,20 @@ func setupOCR2VRFEnvironment(t *testing.T) (testEnvironment *environment.Environ }) } - cd := chainlink.New(0, map[string]interface{}{ + var overrideFn = func(_ interface{}, target interface{}) { + ctf_config.MustConfigOverrideChainlinkVersion(ocr2vrfSmokeConfig.ChainlinkImage, target) + ctf_config.MightConfigOverridePyroscopeKey(ocr2vrfSmokeConfig.Pyroscope, target) + } + + cd := chainlink.NewWithOverride(0, map[string]interface{}{ "replicas": 6, "toml": networks.AddNetworkDetailedConfig( config.BaseOCR2Config, + ocr2vrfSmokeConfig.Pyroscope, config.DefaultOCR2VRFNetworkDetailTomlConfig, testNetwork, ), - }) + }, ocr2vrfSmokeConfig.ChainlinkImage, overrideFn) testEnvironment = environment.New(&environment.Config{ NamespacePrefix: fmt.Sprintf("smoke-ocr2vrf-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")), diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 5f091835894..549d6b0a63b 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -11,17 +11,25 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestOCRBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + config, err := tc.GetConfig("Smoke", tc.OCR) + if err != nil { + t.Fatal(err) + } + + network, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithPrivateEthereumNetwork(network). WithMockAdapter(). WithCLNodes(6). @@ -67,8 +75,14 @@ func TestOCRJobReplacement(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.OCR) + if err != nil { + t.Fatal(err) + } + env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithGeth(). WithMockAdapter(). WithCLNodes(6). diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index dc08b19b16f..f7f5c54069e 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -16,14 +16,22 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestRunLogBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.RunLog) + if err != nil { + t.Fatal(err) + } + env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithGeth(). WithMockAdapter(). WithCLNodes(1). diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 51ea3828cfd..c296fcd0f34 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -17,14 +17,21 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv1" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestVRFBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.VRF) + if err != nil { + t.Fatal(err) + } + env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithGeth(). WithCLNodes(1). WithFunding(big.NewFloat(.1)). @@ -111,9 +118,14 @@ func TestVRFBasic(t *testing.T) { func TestVRFJobReplacement(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.VRF) + if err != nil { + t.Fatal(err) + } env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithGeth(). WithCLNodes(1). WithFunding(big.NewFloat(.1)). diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 7274d8b8772..0d136b62a98 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -9,47 +9,48 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/kelseyhightower/envconfig" "github.com/stretchr/testify/require" commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_config" + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) func TestVRFv2Basic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.VRFv2) + require.NoError(t, err, "Error getting config") + useVRFOwner := false useTestCoordinator := false - - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + network, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") - var vrfv2Config vrfv2_config.VRFV2Config - err = envconfig.Process("VRFV2", &vrfv2Config) - require.NoError(t, err) - env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithPrivateEthereumNetwork(network). WithCLNodes(1). - WithFunding(big.NewFloat(vrfv2Config.ChainlinkNodeFunding)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). Build() require.NoError(t, err, "error creating test env") env.ParallelTransactions(true) - mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(vrfv2Config.LinkNativeFeedResponse)) + mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(*config.VRFv2.General.LinkNativeFeedResponse)) require.NoError(t, err) linkToken, err := actions.DeployLINKToken(env.ContractDeployer) require.NoError(t, err) @@ -60,7 +61,7 @@ func TestVRFv2Basic(t *testing.T) { numberOfTxKeysToCreate := 1 vrfv2Contracts, subIDs, vrfv2Data, err := vrfv2_actions.SetupVRFV2Environment( env, - vrfv2Config, + &config, useVRFOwner, useTestCoordinator, linkToken, @@ -81,7 +82,7 @@ func TestVRFv2Basic(t *testing.T) { vrfv2_actions.LogSubDetails(l, subscription, subID, vrfv2Contracts.Coordinator) t.Run("Request Randomness", func(t *testing.T) { - testConfig := vrfv2Config + configCopy := config.MustCopy().(tc.TestConfig) subBalanceBeforeRequest := subscription.Balance jobRunsBeforeTest, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(vrfv2Data.VRFJob.Data.ID) @@ -89,14 +90,17 @@ func TestVRFv2Basic(t *testing.T) { // test and assert randomWordsFulfilledEvent, err := vrfv2_actions.RequestRandomnessAndWaitForFulfillment( + l, vrfv2Contracts.LoadTestConsumers[0], vrfv2Contracts.Coordinator, - vrfv2Data, subID, - testConfig.RandomnessRequestCountPerRequest, - testConfig, - testConfig.RandomWordsFulfilledEventTimeout, - l, + vrfv2Data, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -115,7 +119,7 @@ func TestVRFv2Basic(t *testing.T) { require.True(t, status.Fulfilled) l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, testConfig.NumberOfWords, uint32(len(status.RandomWords))) + require.Equal(t, *config.VRFv2.General.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -123,10 +127,10 @@ func TestVRFv2Basic(t *testing.T) { }) t.Run("Direct Funding (VRFV2Wrapper)", func(t *testing.T) { - testConfig := vrfv2Config + configCopy := config.MustCopy().(tc.TestConfig) wrapperContracts, wrapperSubID, err := vrfv2_actions.SetupVRFV2WrapperEnvironment( env, - testConfig, + &configCopy, linkToken, mockETHLinkFeed, vrfv2Contracts.Coordinator, @@ -145,14 +149,17 @@ func TestVRFv2Basic(t *testing.T) { // Request Randomness and wait for fulfillment event randomWordsFulfilledEvent, err := vrfv2_actions.DirectFundingRequestRandomnessAndWaitForFulfillment( + l, wrapperConsumer, vrfv2Contracts.Coordinator, - vrfv2Data, *wrapperSubID, - vrfv2Config.RandomnessRequestCountPerRequest, - vrfv2Config, - testConfig.RandomWordsFulfilledEventTimeout, - l, + vrfv2Data, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, ) require.NoError(t, err, "Error requesting randomness and waiting for fulfilment") @@ -175,7 +182,7 @@ func TestVRFv2Basic(t *testing.T) { require.Equal(t, expectedWrapperConsumerJuelsBalance, wrapperConsumerJuelsBalanceAfterRequest) // Check random word count - require.Equal(t, testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) + require.Equal(t, *configCopy.VRFv2.General.NumberOfWords, uint32(len(consumerStatus.RandomWords))) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -196,10 +203,10 @@ func TestVRFv2Basic(t *testing.T) { }) t.Run("Oracle Withdraw", func(t *testing.T) { - testConfig := vrfv2Config + configCopy := config.MustCopy().(tc.TestConfig) subIDsForOracleWithDraw, err := vrfv2_actions.CreateFundSubsAndAddConsumers( env, - testConfig, + big.NewFloat(*configCopy.VRFv2.General.SubscriptionFundingAmountLink), linkToken, vrfv2Contracts.Coordinator, vrfv2Contracts.LoadTestConsumers, @@ -210,14 +217,17 @@ func TestVRFv2Basic(t *testing.T) { subIDForOracleWithdraw := subIDsForOracleWithDraw[0] fulfilledEventLink, err := vrfv2_actions.RequestRandomnessAndWaitForFulfillment( + l, vrfv2Contracts.LoadTestConsumers[0], vrfv2Contracts.Coordinator, - vrfv2Data, subIDForOracleWithdraw, - testConfig.RandomnessRequestCountPerRequest, - testConfig, - testConfig.RandomWordsFulfilledEventTimeout, - l, + vrfv2Data, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, ) require.NoError(t, err) @@ -249,10 +259,10 @@ func TestVRFv2Basic(t *testing.T) { }) t.Run("Canceling Sub And Returning Funds", func(t *testing.T) { - testConfig := vrfv2Config + configCopy := config.MustCopy().(tc.TestConfig) subIDsForCancelling, err := vrfv2_actions.CreateFundSubsAndAddConsumers( env, - testConfig, + big.NewFloat(*configCopy.VRFv2.General.SubscriptionFundingAmountLink), linkToken, vrfv2Contracts.Coordinator, vrfv2Contracts.LoadTestConsumers, @@ -323,14 +333,13 @@ func TestVRFv2Basic(t *testing.T) { }) t.Run("Owner Canceling Sub And Returning Funds While Having Pending Requests", func(t *testing.T) { - testConfig := vrfv2Config - + configCopy := config.MustCopy().(tc.TestConfig) // Underfund subscription to force fulfillments to fail - testConfig.SubscriptionFundingAmountLink = float64(0.000000000000000001) // 1 Juel + configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0.000000000000000001)) // 1 Juel subIDsForCancelling, err := vrfv2_actions.CreateFundSubsAndAddConsumers( env, - testConfig, + big.NewFloat(*configCopy.VRFv2.General.SubscriptionFundingAmountLink), linkToken, vrfv2Contracts.Coordinator, vrfv2Contracts.LoadTestConsumers, @@ -354,14 +363,17 @@ func TestVRFv2Basic(t *testing.T) { // Request randomness - should fail due to underfunded subscription randomWordsFulfilledEventTimeout := 5 * time.Second _, err = vrfv2_actions.RequestRandomnessAndWaitForFulfillment( + l, vrfv2Contracts.LoadTestConsumers[0], vrfv2Contracts.Coordinator, - vrfv2Data, subIDForCancelling, - testConfig.RandomnessRequestCountPerRequest, - testConfig, + vrfv2Data, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, randomWordsFulfilledEventTimeout, - l, ) require.Error(t, err, "Error should occur while waiting for fulfilment due to low sub balance") @@ -438,28 +450,30 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.VRFv2) + if err != nil { + t.Fatal(err) + } + useVRFOwner := false useTestCoordinator := false - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + network, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") - var vrfv2Config vrfv2_config.VRFV2Config - err = envconfig.Process("VRFV2", &vrfv2Config) - require.NoError(t, err) - env, err := test_env.NewCLTestEnvBuilder(). + WithTestConfig(&config). WithTestInstance(t). WithPrivateEthereumNetwork(network). WithCLNodes(1). - WithFunding(big.NewFloat(vrfv2Config.ChainlinkNodeFunding)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). Build() require.NoError(t, err, "error creating test env") env.ParallelTransactions(true) - mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(vrfv2Config.LinkNativeFeedResponse)) + mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(*config.VRFv2.General.LinkNativeFeedResponse)) require.NoError(t, err) linkToken, err := actions.DeployLINKToken(env.ContractDeployer) require.NoError(t, err) @@ -470,7 +484,7 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { numberOfTxKeysToCreate := 2 vrfv2Contracts, subIDs, vrfv2Data, err := vrfv2_actions.SetupVRFV2Environment( env, - vrfv2Config, + &config, useVRFOwner, useTestCoordinator, linkToken, @@ -491,7 +505,6 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { vrfv2_actions.LogSubDetails(l, subscription, subID, vrfv2Contracts.Coordinator) t.Run("Request Randomness with multiple sending keys", func(t *testing.T) { - testConfig := vrfv2Config txKeys, _, err := env.ClCluster.Nodes[0].API.ReadTxKeys("evm") require.NoError(t, err, "error reading tx keys") @@ -500,14 +513,17 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { var fulfillmentTxFromAddresses []string for i := 0; i < numberOfTxKeysToCreate+1; i++ { randomWordsFulfilledEvent, err := vrfv2_actions.RequestRandomnessAndWaitForFulfillment( + l, vrfv2Contracts.LoadTestConsumers[0], vrfv2Contracts.Coordinator, - vrfv2Data, subID, - testConfig.RandomnessRequestCountPerRequest, - testConfig, - testConfig.RandomWordsFulfilledEventTimeout, - l, + vrfv2Data, + *config.VRFv2.General.MinimumConfirmations, + *config.VRFv2.General.CallbackGasLimit, + *config.VRFv2.General.NumberOfWords, + *config.VRFv2.General.RandomnessRequestCountPerRequest, + *config.VRFv2.General.RandomnessRequestCountPerRequestDeviation, + config.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -534,28 +550,27 @@ func TestVRFOwner(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + config, err := tc.GetConfig("Smoke", tc.VRFv2) + require.NoError(t, err, "Error getting config") + useVRFOwner := true useTestCoordinator := true - - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) + network, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") - var vrfv2Config vrfv2_config.VRFV2Config - err = envconfig.Process("VRFV2", &vrfv2Config) - require.NoError(t, err) - env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithPrivateEthereumNetwork(network). WithCLNodes(1). - WithFunding(big.NewFloat(vrfv2Config.ChainlinkNodeFunding)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). Build() require.NoError(t, err, "error creating test env") env.ParallelTransactions(true) - mockETHLinkFeed, err := env.ContractDeployer.DeployVRFMockETHLINKFeed(big.NewInt(vrfv2Config.LinkNativeFeedResponse)) + mockETHLinkFeed, err := env.ContractDeployer.DeployVRFMockETHLINKFeed(big.NewInt(*config.VRFv2.General.LinkNativeFeedResponse)) require.NoError(t, err) linkToken, err := actions.DeployLINKToken(env.ContractDeployer) @@ -567,7 +582,7 @@ func TestVRFOwner(t *testing.T) { numberOfTxKeysToCreate := 1 vrfv2Contracts, subIDs, vrfv2Data, err := vrfv2_actions.SetupVRFV2Environment( env, - vrfv2Config, + &config, useVRFOwner, useTestCoordinator, linkToken, @@ -588,7 +603,7 @@ func TestVRFOwner(t *testing.T) { vrfv2_actions.LogSubDetails(l, subscription, subID, vrfv2Contracts.Coordinator) t.Run("Request Randomness With Force-Fulfill", func(t *testing.T) { - testConfig := vrfv2Config + configCopy := config.MustCopy().(tc.TestConfig) vrfCoordinatorOwner, err := vrfv2Contracts.Coordinator.GetOwner(testcontext.Get(t)) require.NoError(t, err) @@ -617,16 +632,19 @@ func TestVRFOwner(t *testing.T) { // test and assert _, randFulfilledEvent, _, err := vrfv2_actions.RequestRandomnessWithForceFulfillAndWaitForFulfillment( + l, vrfv2Contracts.LoadTestConsumers[0], vrfv2Contracts.Coordinator, vrfv2Contracts.VRFOwner, vrfv2Data, - testConfig.RandomnessRequestCountPerRequest, - testConfig, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, conversions.EtherToWei(big.NewFloat(5)), common.HexToAddress(linkToken.Address()), time.Minute*2, - l, ) require.NoError(t, err, "error requesting randomness with force-fulfillment and waiting for fulfilment") require.Equal(t, 0, randFulfilledEvent.Payment.Cmp(big.NewInt(0)), "Forced Fulfilled Randomness's Payment should be 0") @@ -636,7 +654,7 @@ func TestVRFOwner(t *testing.T) { require.True(t, status.Fulfilled) l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, testConfig.NumberOfWords, uint32(len(status.RandomWords))) + require.Equal(t, *configCopy.VRFv2.General.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -651,11 +669,11 @@ func TestVRFOwner(t *testing.T) { coordinatorFallbackWeiPerUnitLinkConfig, err := vrfv2Contracts.Coordinator.GetFallbackWeiPerUnitLink(testcontext.Get(t)) require.NoError(t, err, "error getting coordinator FallbackWeiPerUnitLink") - require.Equal(t, testConfig.StalenessSeconds, coordinatorConfig.StalenessSeconds) - require.Equal(t, testConfig.GasAfterPaymentCalculation, coordinatorConfig.GasAfterPaymentCalculation) - require.Equal(t, testConfig.MinimumConfirmations, coordinatorConfig.MinimumRequestConfirmations) - require.Equal(t, testConfig.FulfillmentFlatFeeLinkPPMTier1, coordinatorFeeConfig.FulfillmentFlatFeeLinkPPMTier1) - require.Equal(t, testConfig.ReqsForTier2, coordinatorFeeConfig.ReqsForTier2.Int64()) - require.Equal(t, testConfig.FallbackWeiPerUnitLink, coordinatorFallbackWeiPerUnitLinkConfig.Int64()) + require.Equal(t, *configCopy.VRFv2.General.StalenessSeconds, coordinatorConfig.StalenessSeconds) + require.Equal(t, *configCopy.VRFv2.General.GasAfterPaymentCalculation, coordinatorConfig.GasAfterPaymentCalculation) + require.Equal(t, *configCopy.VRFv2.General.MinimumConfirmations, coordinatorConfig.MinimumRequestConfirmations) + require.Equal(t, *configCopy.VRFv2.General.FulfillmentFlatFeeLinkPPMTier1, coordinatorFeeConfig.FulfillmentFlatFeeLinkPPMTier1) + require.Equal(t, *configCopy.VRFv2.General.ReqsForTier2, coordinatorFeeConfig.ReqsForTier2.Int64()) + require.Equal(t, *configCopy.VRFv2.General.FallbackWeiPerUnitLink, coordinatorFallbackWeiPerUnitLinkConfig.Int64()) }) } diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index 5417e61d5ed..f1f11d3e1f0 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -10,18 +10,19 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/kelseyhightower/envconfig" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils" ) @@ -29,25 +30,28 @@ func TestVRFv2Plus(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) - require.NoError(t, err, "Error building ethereum network config") + config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + if err != nil { + t.Fatal(err) + } - var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig - err = envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) - require.NoError(t, err) + network, err := actions.EthereumNetworkConfigFromConfig(l, &config) + require.NoError(t, err, "Error building ethereum network config") env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithPrivateEthereumNetwork(network). + WithGeth(). WithCLNodes(1). - WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). Build() require.NoError(t, err, "error creating test env") env.ParallelTransactions(true) - mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(vrfv2PlusConfig.LinkNativeFeedResponse)) + mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(*config.VRFv2Plus.General.LinkNativeFeedResponse)) require.NoError(t, err, "error deploying mock ETH/LINK feed") linkToken, err := actions.DeployLINKToken(env.ContractDeployer) @@ -59,7 +63,7 @@ func TestVRFv2Plus(t *testing.T) { numberOfTxKeysToCreate := 2 vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment( env, - vrfv2PlusConfig, + &config, linkToken, mockETHLinkFeed, numberOfTxKeysToCreate, @@ -77,7 +81,7 @@ func TestVRFv2Plus(t *testing.T) { vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator) t.Run("Link Billing", func(t *testing.T) { - testConfig := vrfv2PlusConfig + configCopy := config.MustCopy().(tc.TestConfig) var isNativeBilling = false subBalanceBeforeRequest := subscription.Balance @@ -91,9 +95,12 @@ func TestVRFv2Plus(t *testing.T) { vrfv2PlusData, subID, isNativeBilling, - testConfig.RandomnessRequestCountPerRequest, - testConfig, - testConfig.RandomWordsFulfilledEventTimeout, + *configCopy.VRFv2Plus.General.MinimumConfirmations, + *configCopy.VRFv2Plus.General.CallbackGasLimit, + *configCopy.VRFv2Plus.General.NumberOfWords, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -113,7 +120,7 @@ func TestVRFv2Plus(t *testing.T) { require.True(t, status.Fulfilled) l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, testConfig.NumberOfWords, uint32(len(status.RandomWords))) + require.Equal(t, *configCopy.VRFv2Plus.General.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -121,7 +128,8 @@ func TestVRFv2Plus(t *testing.T) { }) t.Run("Native Billing", func(t *testing.T) { - testConfig := vrfv2PlusConfig + configCopy := config.MustCopy().(tc.TestConfig) + testConfig := configCopy.VRFv2Plus.General var isNativeBilling = true subNativeTokenBalanceBeforeRequest := subscription.NativeBalance @@ -135,9 +143,12 @@ func TestVRFv2Plus(t *testing.T) { vrfv2PlusData, subID, isNativeBilling, - testConfig.RandomnessRequestCountPerRequest, - testConfig, - testConfig.RandomWordsFulfilledEventTimeout, + *configCopy.VRFv2Plus.General.MinimumConfirmations, + *configCopy.VRFv2Plus.General.CallbackGasLimit, + *configCopy.VRFv2Plus.General.NumberOfWords, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -156,17 +167,17 @@ func TestVRFv2Plus(t *testing.T) { require.True(t, status.Fulfilled) l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, testConfig.NumberOfWords, uint32(len(status.RandomWords))) + require.Equal(t, *testConfig.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") } }) t.Run("Direct Funding (VRFV2PlusWrapper)", func(t *testing.T) { - testConfig := vrfv2PlusConfig + configCopy := config.MustCopy().(tc.TestConfig) wrapperContracts, wrapperSubID, err := vrfv2plus.SetupVRFV2PlusWrapperEnvironment( env, - testConfig, + &configCopy, linkToken, mockETHLinkFeed, vrfv2PlusContracts.Coordinator, @@ -176,7 +187,8 @@ func TestVRFv2Plus(t *testing.T) { require.NoError(t, err) t.Run("Link Billing", func(t *testing.T) { - testConfig := vrfv2PlusConfig + configCopy := config.MustCopy().(tc.TestConfig) + testConfig := configCopy.VRFv2Plus.General var isNativeBilling = false wrapperConsumerJuelsBalanceBeforeRequest, err := linkToken.BalanceOf(testcontext.Get(t), wrapperContracts.LoadTestConsumers[0].Address()) @@ -192,8 +204,12 @@ func TestVRFv2Plus(t *testing.T) { vrfv2PlusData, wrapperSubID, isNativeBilling, - testConfig, - testConfig.RandomWordsFulfilledEventTimeout, + *configCopy.VRFv2Plus.General.MinimumConfirmations, + *configCopy.VRFv2Plus.General.CallbackGasLimit, + *configCopy.VRFv2Plus.General.NumberOfWords, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -218,14 +234,15 @@ func TestVRFv2Plus(t *testing.T) { //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub") vrfv2plus.LogFulfillmentDetailsLinkBilling(l, wrapperConsumerJuelsBalanceBeforeRequest, wrapperConsumerJuelsBalanceAfterRequest, consumerStatus, randomWordsFulfilledEvent) - require.Equal(t, testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) + require.Equal(t, *testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") } }) t.Run("Native Billing", func(t *testing.T) { - testConfig := vrfv2PlusConfig + configCopy := config.MustCopy().(tc.TestConfig) + testConfig := configCopy.VRFv2Plus.General var isNativeBilling = true wrapperConsumerBalanceBeforeRequestWei, err := env.EVMClient.BalanceAt(testcontext.Get(t), common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address())) @@ -241,8 +258,12 @@ func TestVRFv2Plus(t *testing.T) { vrfv2PlusData, wrapperSubID, isNativeBilling, - testConfig, - testConfig.RandomWordsFulfilledEventTimeout, + *configCopy.VRFv2Plus.General.MinimumConfirmations, + *configCopy.VRFv2Plus.General.CallbackGasLimit, + *configCopy.VRFv2Plus.General.NumberOfWords, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -267,7 +288,7 @@ func TestVRFv2Plus(t *testing.T) { //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub") vrfv2plus.LogFulfillmentDetailsNativeBilling(l, wrapperConsumerBalanceBeforeRequestWei, wrapperConsumerBalanceAfterRequestWei, consumerStatus, randomWordsFulfilledEvent) - require.Equal(t, testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) + require.Equal(t, *testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -275,14 +296,16 @@ func TestVRFv2Plus(t *testing.T) { }) }) t.Run("Canceling Sub And Returning Funds", func(t *testing.T) { - testConfig := vrfv2PlusConfig + configCopy := config.MustCopy().(tc.TestConfig) subIDsForCancelling, err := vrfv2plus.CreateFundSubsAndAddConsumers( env, - testConfig, + big.NewFloat(*configCopy.GetVRFv2PlusConfig().General.SubscriptionFundingAmountNative), + big.NewFloat(*configCopy.GetVRFv2PlusConfig().General.SubscriptionFundingAmountLink), linkToken, vrfv2PlusContracts.Coordinator, vrfv2PlusContracts.LoadTestConsumers, 1, + vrfv2plus_config.BillingType(*configCopy.GetVRFv2PlusConfig().General.SubscriptionBillingType), ) require.NoError(t, err) subIDForCancelling := subIDsForCancelling[0] @@ -367,18 +390,22 @@ func TestVRFv2Plus(t *testing.T) { }) t.Run("Owner Canceling Sub And Returning Funds While Having Pending Requests", func(t *testing.T) { - testConfig := vrfv2PlusConfig + configCopy := config.MustCopy().(tc.TestConfig) + testConfig := configCopy.VRFv2Plus.General + //underfund subs in order rand fulfillments to fail - testConfig.SubscriptionFundingAmountNative = float64(0.000000000000000001) //1 Wei - testConfig.SubscriptionFundingAmountLink = float64(0.000000000000000001) //1 Juels + testConfig.SubscriptionFundingAmountNative = ptr.Ptr(float64(0.000000000000000001)) //1 Wei + testConfig.SubscriptionFundingAmountLink = ptr.Ptr(float64(0.000000000000000001)) //1 Juels subIDsForCancelling, err := vrfv2plus.CreateFundSubsAndAddConsumers( env, - testConfig, + big.NewFloat(*configCopy.GetVRFv2PlusConfig().General.SubscriptionFundingAmountNative), + big.NewFloat(*configCopy.GetVRFv2PlusConfig().General.SubscriptionFundingAmountLink), linkToken, vrfv2PlusContracts.Coordinator, vrfv2PlusContracts.LoadTestConsumers, 1, + vrfv2plus_config.BillingType(*configCopy.GetVRFv2PlusConfig().General.SubscriptionBillingType), ) require.NoError(t, err) @@ -405,8 +432,11 @@ func TestVRFv2Plus(t *testing.T) { vrfv2PlusData, subIDForCancelling, false, - testConfig.RandomnessRequestCountPerRequest, - testConfig, + *configCopy.VRFv2Plus.General.MinimumConfirmations, + *configCopy.VRFv2Plus.General.CallbackGasLimit, + *configCopy.VRFv2Plus.General.NumberOfWords, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, randomWordsFulfilledEventTimeout, l, ) @@ -419,8 +449,11 @@ func TestVRFv2Plus(t *testing.T) { vrfv2PlusData, subIDForCancelling, true, - testConfig.RandomnessRequestCountPerRequest, - testConfig, + *configCopy.VRFv2Plus.General.MinimumConfirmations, + *configCopy.VRFv2Plus.General.CallbackGasLimit, + *configCopy.VRFv2Plus.General.NumberOfWords, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, randomWordsFulfilledEventTimeout, l, ) @@ -523,14 +556,16 @@ func TestVRFv2Plus(t *testing.T) { }) t.Run("Owner Withdraw", func(t *testing.T) { - testConfig := vrfv2PlusConfig + configCopy := config.MustCopy().(tc.TestConfig) subIDsForWithdraw, err := vrfv2plus.CreateFundSubsAndAddConsumers( env, - testConfig, + big.NewFloat(*configCopy.GetVRFv2PlusConfig().General.SubscriptionFundingAmountNative), + big.NewFloat(*configCopy.GetVRFv2PlusConfig().General.SubscriptionFundingAmountLink), linkToken, vrfv2PlusContracts.Coordinator, vrfv2PlusContracts.LoadTestConsumers, 1, + vrfv2plus_config.BillingType(*configCopy.GetVRFv2PlusConfig().General.SubscriptionBillingType), ) require.NoError(t, err) subIDForWithdraw := subIDsForWithdraw[0] @@ -541,9 +576,12 @@ func TestVRFv2Plus(t *testing.T) { vrfv2PlusData, subIDForWithdraw, false, - testConfig.RandomnessRequestCountPerRequest, - testConfig, - testConfig.RandomWordsFulfilledEventTimeout, + *configCopy.VRFv2Plus.General.MinimumConfirmations, + *configCopy.VRFv2Plus.General.CallbackGasLimit, + *configCopy.VRFv2Plus.General.NumberOfWords, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, l, ) require.NoError(t, err) @@ -554,9 +592,12 @@ func TestVRFv2Plus(t *testing.T) { vrfv2PlusData, subIDForWithdraw, true, - testConfig.RandomnessRequestCountPerRequest, - testConfig, - testConfig.RandomWordsFulfilledEventTimeout, + *configCopy.VRFv2Plus.General.MinimumConfirmations, + *configCopy.VRFv2Plus.General.CallbackGasLimit, + *configCopy.VRFv2Plus.General.NumberOfWords, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, l, ) require.NoError(t, err) @@ -608,25 +649,27 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) - require.NoError(t, err, "Error building ethereum network config") + config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + if err != nil { + t.Fatal(err) + } - var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig - err = envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) - require.NoError(t, err) + network, err := actions.EthereumNetworkConfigFromConfig(l, &config) + require.NoError(t, err, "Error building ethereum network config") env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithPrivateEthereumNetwork(network). WithCLNodes(1). - WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). Build() require.NoError(t, err, "error creating test env") env.ParallelTransactions(true) - mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(vrfv2PlusConfig.LinkNativeFeedResponse)) + mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(*config.VRFv2Plus.General.LinkNativeFeedResponse)) require.NoError(t, err, "error deploying mock ETH/LINK feed") linkToken, err := actions.DeployLINKToken(env.ContractDeployer) @@ -635,7 +678,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { numberOfTxKeysToCreate := 2 vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment( env, - vrfv2PlusConfig, + &config, linkToken, mockETHLinkFeed, numberOfTxKeysToCreate, @@ -653,7 +696,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator) t.Run("Request Randomness with multiple sending keys", func(t *testing.T) { - testConfig := vrfv2PlusConfig + configCopy := config.MustCopy().(tc.TestConfig) var isNativeBilling = false txKeys, _, err := env.ClCluster.Nodes[0].API.ReadTxKeys("evm") require.NoError(t, err, "error reading tx keys") @@ -668,9 +711,12 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { vrfv2PlusData, subID, isNativeBilling, - testConfig.RandomnessRequestCountPerRequest, - testConfig, - testConfig.RandomWordsFulfilledEventTimeout, + *configCopy.VRFv2Plus.General.MinimumConfirmations, + *configCopy.VRFv2Plus.General.CallbackGasLimit, + *configCopy.VRFv2Plus.General.NumberOfWords, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -698,24 +744,26 @@ func TestVRFv2PlusMigration(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - network, err := actions.EthereumNetworkConfigFromEnvOrDefault(l) - require.NoError(t, err, "Error building ethereum network config") + config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + if err != nil { + t.Fatal(err) + } - var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig - err = envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) - require.NoError(t, err) + network, err := actions.EthereumNetworkConfigFromConfig(l, &config) + require.NoError(t, err, "Error building ethereum network config") env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). + WithTestConfig(&config). WithPrivateEthereumNetwork(network). WithCLNodes(1). - WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). Build() require.NoError(t, err, "error creating test env") env.ParallelTransactions(true) - mockETHLinkFeedAddress, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(vrfv2PlusConfig.LinkNativeFeedResponse)) + mockETHLinkFeedAddress, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(*config.VRFv2Plus.General.LinkNativeFeedResponse)) require.NoError(t, err, "error deploying mock ETH/LINK feed") linkAddress, err := actions.DeployLINKToken(env.ContractDeployer) @@ -723,7 +771,7 @@ func TestVRFv2PlusMigration(t *testing.T) { vrfv2PlusContracts, subIDs, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment( env, - vrfv2PlusConfig, + &config, linkAddress, mockETHLinkFeedAddress, 0, @@ -758,15 +806,16 @@ func TestVRFv2PlusMigration(t *testing.T) { _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfv2PlusData.VRFKey, newCoordinator) require.NoError(t, err, fmt.Errorf("%s, err: %w", vrfv2plus.ErrRegisteringProvingKey, err)) + vrfv2PlusConfig := config.VRFv2Plus.General err = newCoordinator.SetConfig( - vrfv2PlusConfig.MinimumConfirmations, - vrfv2PlusConfig.MaxGasLimitCoordinatorConfig, - vrfv2PlusConfig.StalenessSeconds, - vrfv2PlusConfig.GasAfterPaymentCalculation, - big.NewInt(vrfv2PlusConfig.LinkNativeFeedResponse), + *vrfv2PlusConfig.MinimumConfirmations, + *vrfv2PlusConfig.MaxGasLimitCoordinatorConfig, + *vrfv2PlusConfig.StalenessSeconds, + *vrfv2PlusConfig.GasAfterPaymentCalculation, + big.NewInt(*vrfv2PlusConfig.LinkNativeFeedResponse), vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionFeeConfig{ - FulfillmentFlatFeeLinkPPM: vrfv2PlusConfig.FulfillmentFlatFeeLinkPPM, - FulfillmentFlatFeeNativePPM: vrfv2PlusConfig.FulfillmentFlatFeeNativePPM, + FulfillmentFlatFeeLinkPPM: *vrfv2PlusConfig.FulfillmentFlatFeeLinkPPM, + FulfillmentFlatFeeNativePPM: *vrfv2PlusConfig.FulfillmentFlatFeeNativePPM, }, ) require.NoError(t, err) @@ -781,7 +830,7 @@ func TestVRFv2PlusMigration(t *testing.T) { CoordinatorAddress: newCoordinator.Address(), FromAddresses: []string{vrfv2PlusData.PrimaryEthAddress}, EVMChainID: vrfv2PlusData.ChainID.String(), - MinIncomingConfirmations: int(vrfv2PlusConfig.MinimumConfirmations), + MinIncomingConfirmations: int(*vrfv2PlusConfig.MinimumConfirmations), PublicKey: vrfv2PlusData.VRFKey.Data.ID, EstimateGasMultiplier: 1, BatchFulfillmentEnabled: false, @@ -878,7 +927,11 @@ func TestVRFv2PlusMigration(t *testing.T) { vrfv2PlusData, subID, false, - vrfv2PlusConfig, + *config.VRFv2Plus.General.MinimumConfirmations, + *config.VRFv2Plus.General.CallbackGasLimit, + *config.VRFv2Plus.General.NumberOfWords, + *config.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *config.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -890,9 +943,12 @@ func TestVRFv2PlusMigration(t *testing.T) { vrfv2PlusData, subID, true, - vrfv2PlusConfig, + *config.VRFv2Plus.General.MinimumConfirmations, + *config.VRFv2Plus.General.CallbackGasLimit, + *config.VRFv2Plus.General.NumberOfWords, + *config.VRFv2Plus.General.RandomnessRequestCountPerRequest, + *config.VRFv2Plus.General.RandomnessRequestCountPerRequestDeviation, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") - } diff --git a/integration-tests/soak/forwarder_ocr_test.go b/integration-tests/soak/forwarder_ocr_test.go index 538f5ff1569..b5355a6c3f5 100644 --- a/integration-tests/soak/forwarder_ocr_test.go +++ b/integration-tests/soak/forwarder_ocr_test.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" ) @@ -21,9 +22,12 @@ ForwardersEnabled = true` // fmt.Println(networks.AddNetworkDetailedConfig(config.BaseOCRP2PV1Config, customNetworkTOML, network)) // fmt.Println("---------------------") - ocrSoakTest, err := testsetups.NewOCRSoakTest(t, true) + config, err := tc.GetConfig("Soak", tc.OCR) + require.NoError(t, err, "Error getting config") + + ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, true) require.NoError(t, err, "Error creating soak test") - ocrSoakTest.DeployEnvironment(customNetworkTOML) + ocrSoakTest.DeployEnvironment(customNetworkTOML, &config) if ocrSoakTest.Environment().WillUseRemoteRunner() { return } @@ -32,6 +36,6 @@ ForwardersEnabled = true` l.Error().Err(err).Msg("Error tearing down environment") } }) - ocrSoakTest.Setup() + ocrSoakTest.Setup(&config) ocrSoakTest.Run() } diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go index 4d7971d678e..e25391e8450 100644 --- a/integration-tests/soak/ocr_test.go +++ b/integration-tests/soak/ocr_test.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" ) @@ -21,10 +22,13 @@ func TestOCRSoak(t *testing.T) { // fmt.Println(networks.AddNetworkDetailedConfig(config.BaseOCR1Config, customNetworkTOML, network)) // fmt.Println("---------------------") - ocrSoakTest, err := testsetups.NewOCRSoakTest(t, false) + config, err := tc.GetConfig("Soak", tc.OCR) + require.NoError(t, err, "Error getting config") + + ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, false) require.NoError(t, err, "Error creating soak test") if !ocrSoakTest.Interrupted() { - ocrSoakTest.DeployEnvironment(customNetworkTOML) + ocrSoakTest.DeployEnvironment(customNetworkTOML, &config) } if ocrSoakTest.Environment().WillUseRemoteRunner() { return @@ -39,7 +43,7 @@ func TestOCRSoak(t *testing.T) { require.NoError(t, err, "Error loading state") ocrSoakTest.Resume() } else { - ocrSoakTest.Setup() + ocrSoakTest.Setup(&config) ocrSoakTest.Run() } } diff --git a/integration-tests/testconfig/automation/automation.toml b/integration-tests/testconfig/automation/automation.toml new file mode 100644 index 00000000000..58b95f9b4cc --- /dev/null +++ b/integration-tests/testconfig/automation/automation.toml @@ -0,0 +1,49 @@ +# product defaults +[Common] +chainlink_node_funding = 0.5 + +# reorg test specific overrides +[Reorg.Automation] +[Reorg.Automation.General] +number_of_nodes=6 +duration=100 +block_time=1 +spec_type="minimum" +chainlink_node_log_level="info" +use_prometheus=false + +# load test specific overrides +[Load.Common] +chainlink_node_funding = 100 + +[Load.Automation] +[Load.Automation.General] +number_of_nodes=6 +duration=900 +block_time=1 +spec_type="minimum" +chainlink_node_log_level="info" +use_prometheus=false + +[[Load.Automation.Load]] +number_of_upkeeps=5 +number_of_events = 1 +number_of_spam_matching_events = 1 +number_of_spam_non_matching_events = 0 +check_burn_amount = 0 +perform_burn_amount = 0 +upkeep_gas_limit = 1000000 +shared_trigger = false + +[[Load.Automation.Load]] +number_of_upkeeps=5 +number_of_events = 1 +number_of_spam_matching_events = 0 +number_of_spam_non_matching_events = 1 +check_burn_amount = 0 +perform_burn_amount = 0 +upkeep_gas_limit = 1000000 +shared_trigger = true + +[Load.Pyroscope] +enabled=false \ No newline at end of file diff --git a/integration-tests/testconfig/automation/config.go b/integration-tests/testconfig/automation/config.go new file mode 100644 index 00000000000..4431a640d0d --- /dev/null +++ b/integration-tests/testconfig/automation/config.go @@ -0,0 +1,91 @@ +package automation + +import ( + "errors" + "math/big" +) + +type Config struct { + General *General `toml:"General"` + Load []Load `toml:"Load"` +} + +func (c *Config) Validate() error { + if c.General != nil { + if err := c.General.Validate(); err != nil { + return err + } + } + if len(c.Load) > 0 { + for _, load := range c.Load { + if err := load.Validate(); err != nil { + return err + } + } + } + return nil +} + +// General is a common configuration for all automation performance tests +type General struct { + NumberOfNodes *int `toml:"number_of_nodes"` + Duration *int `toml:"duration"` + BlockTime *int `toml:"block_time"` + SpecType *string `toml:"spec_type"` + ChainlinkNodeLogLevel *string `toml:"chainlink_node_log_level"` + UsePrometheus *bool `toml:"use_prometheus"` +} + +func (c *General) Validate() error { + if c.NumberOfNodes == nil || *c.NumberOfNodes < 1 { + return errors.New("number_of_nodes must be set to a positive integer") + } + if c.Duration == nil || *c.Duration < 1 { + return errors.New("duration must be set to a positive integer") + } + if c.BlockTime == nil || *c.BlockTime < 1 { + return errors.New("block_time must be set to a positive integer") + } + if c.SpecType == nil { + return errors.New("spec_type must be set") + } + if c.ChainlinkNodeLogLevel == nil { + return errors.New("chainlink_node_log_level must be set") + } + + return nil +} + +type Load struct { + NumberOfUpkeeps *int `toml:"number_of_upkeeps"` + NumberOfEvents *int `toml:"number_of_events"` + NumberOfSpamMatchingEvents *int `toml:"number_of_spam_matching_events"` + NumberOfSpamNonMatchingEvents *int `toml:"number_of_spam_non_matching_events"` + CheckBurnAmount *big.Int `toml:"check_burn_amount"` + PerformBurnAmount *big.Int `toml:"perform_burn_amount"` + SharedTrigger *bool `toml:"shared_trigger"` + UpkeepGasLimit *uint32 `toml:"upkeep_gas_limit"` +} + +func (c *Load) Validate() error { + if c.NumberOfUpkeeps == nil || *c.NumberOfUpkeeps < 1 { + return errors.New("number_of_upkeeps must be set to a positive integer") + } + if c.NumberOfEvents == nil || *c.NumberOfEvents < 0 { + return errors.New("number_of_events must be set to a non-negative integer") + } + if c.NumberOfSpamMatchingEvents == nil || *c.NumberOfSpamMatchingEvents < 0 { + return errors.New("number_of_spam_matching_events must be set to a non-negative integer") + } + if c.NumberOfSpamNonMatchingEvents == nil || *c.NumberOfSpamNonMatchingEvents < 0 { + return errors.New("number_of_spam_non_matching_events must be set to a non-negative integer") + } + if c.CheckBurnAmount == nil || c.CheckBurnAmount.Cmp(big.NewInt(0)) < 0 { + return errors.New("check_burn_amount must be set to a non-negative integer") + } + if c.PerformBurnAmount == nil || c.PerformBurnAmount.Cmp(big.NewInt(0)) < 0 { + return errors.New("perform_burn_amount must be set to a non-negative integer") + } + + return nil +} diff --git a/integration-tests/testconfig/automation/example.toml b/integration-tests/testconfig/automation/example.toml new file mode 100644 index 00000000000..a8e0510d83c --- /dev/null +++ b/integration-tests/testconfig/automation/example.toml @@ -0,0 +1,90 @@ +# Example of full config with all fields +# General part +[ChainlinkImage] +image="public.ecr.aws/chainlink/chainlink" +version="2.7.0" + +[Logging] +# if set to true will save logs even if test did not fail +test_log_collect=false + +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth="loki-basic-auth" +# only needed for cloud grafana +bearer_token="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +bearer_token="my-awesome-token" + +# if you want to use polygon_mumbial +[Network] +selected_networks=["polygon_mumbai"] + +[Network.RpcHttpUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.RpcWsUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.WalletKeys] +polygon_mumbai = ["change-me-to-your-PK"] + +[PrivateEthereumNetwork] +# pos or pow +consensus_type="pos" +# only prysm supported currently +consensus_layer="prysm" +# geth, besu, nethermind or erigon +execution_layer="geth" +# if true after env started it will wait for at least 1 epoch to be finalised before continuing +wait_for_finalization=false + +[PrivateEthereumNetwork.EthereumChainConfig] +# duration of single slot, lower => faster block production, must be >= 4 +seconds_per_slot=12 +# numer of slots in epoch, lower => faster epoch finalisation, must be >= 4 +slots_per_epoch=6 +# extra genesis gelay, no need to modify, but it should be after all validators/beacon chain starts +genesis_delay=15 +# number of validators in the network +validator_count=8 +chain_id=1337 +# list of addresses to be prefunded in genesis +addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] + +# Common +[Common] +chainlink_node_funding = 0.5 + +# Product part +[Automation] +[Automation.General] +number_of_nodes=6 +duration=100 +block_time=1 +number_of_events=1 +spec_type="minimum" +chainlink_node_log_level="info" +use_prometheus=false + +# upgrade test specific override +[TestAutomationNodeUpgrade.ChainlinkUpgradeImage] +image="public.ecr.aws/chainlink/chainlink" +version="2.8.0" \ No newline at end of file diff --git a/integration-tests/testconfig/configs_embed.go b/integration-tests/testconfig/configs_embed.go new file mode 100644 index 00000000000..67e954ff503 --- /dev/null +++ b/integration-tests/testconfig/configs_embed.go @@ -0,0 +1,21 @@ +//go:build embed +// +build embed + +package testconfig + +import "embed" + +//go:embed default.toml +//go:embed automation/automation.toml +//go:embed functions/functions.toml +//go:embed keeper/keeper.toml +//go:embed log_poller/log_poller.toml +//go:embed node/node.toml +//go:embed ocr/ocr.toml +//go:embed vrfv2/vrfv2.toml +//go:embed vrfv2plus/vrfv2plus.toml +var embeddedConfigsFs embed.FS + +func init() { + areConfigsEmbedded = true +} diff --git a/integration-tests/testconfig/configs_noembed.go b/integration-tests/testconfig/configs_noembed.go new file mode 100644 index 00000000000..95572c4a044 --- /dev/null +++ b/integration-tests/testconfig/configs_noembed.go @@ -0,0 +1,12 @@ +//go:build !embed +// +build !embed + +package testconfig + +import "embed" + +var embeddedConfigsFs embed.FS + +func init() { + areConfigsEmbedded = false +} diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml new file mode 100644 index 00000000000..a65c23d70dc --- /dev/null +++ b/integration-tests/testconfig/default.toml @@ -0,0 +1,22 @@ +[Logging] +test_log_collect=false + +[Logging.LogStream] +log_targets=["file"] +log_producer_timeout="10s" +log_producer_retry_limit=10 + +[Network] +selected_networks=["simulated"] + +[PrivateEthereumNetwork] +consensus_type="pow" +execution_layer="geth" + +[PrivateEthereumNetwork.EthereumChainConfig] +seconds_per_slot=3 +slots_per_epoch=2 +genesis_delay=15 +validator_count=4 +chain_id=1337 +addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] \ No newline at end of file diff --git a/integration-tests/testconfig/functions/config.go b/integration-tests/testconfig/functions/config.go new file mode 100644 index 00000000000..88c0e052951 --- /dev/null +++ b/integration-tests/testconfig/functions/config.go @@ -0,0 +1,118 @@ +package functions + +import ( + "errors" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/utils/net" +) + +const ( + ErrReadPerfConfig = "failed to read TOML config for performance tests" + ErrUnmarshalPerfConfig = "failed to unmarshal TOML config for performance tests" +) + +type Config struct { + Performance *Performance `toml:"Performance"` + Common *Common `toml:"Common"` +} + +type Common struct { + NodeFunds *big.Float `toml:"node_funds"` + SubFunds *big.Int `toml:"sub_funds"` + LINKTokenAddr *string `toml:"link_token_addr"` + Coordinator *string `toml:"coordinator_addr"` + Router *string `toml:"router_addr"` + LoadTestClient *string `toml:"client_addr"` + SubscriptionID *uint64 `toml:"subscription_id"` + DONID *string `toml:"don_id"` + GatewayURL *string `toml:"gateway_url"` + Receiver *string `toml:"receiver"` + FunctionsCallPayloadHTTP *string `toml:"functions_call_payload_http"` + FunctionsCallPayloadWithSecrets *string `toml:"functions_call_payload_with_secrets"` + FunctionsCallPayloadReal *string `toml:"functions_call_payload_real"` + SecretsSlotID *uint8 `toml:"secrets_slot_id"` + SecretsVersionID *uint64 `toml:"secrets_version_id"` + // Secrets these are for CI secrets + Secrets *string `toml:"secrets"` +} + +func (c *Common) Validate() error { + if c.SubFunds == nil { + return errors.New("sub_funds must be set") + } + if c.LINKTokenAddr == nil || *c.LINKTokenAddr == "" { + return errors.New("link_token_addr must be set") + } + if !common.IsHexAddress(*c.LINKTokenAddr) { + return errors.New("link_token_addr must be a valid address") + } + if c.Coordinator == nil || *c.Coordinator == "" { + return errors.New("coordinator must be set") + } + if !common.IsHexAddress(*c.Coordinator) { + return errors.New("coordinator must be a valid address") + } + if c.Router == nil || *c.Router == "" { + return errors.New("router must be set") + } + if !common.IsHexAddress(*c.Router) { + return errors.New("router must be a valid address") + } + if c.DONID == nil || *c.DONID == "" { + return errors.New("don_id must be set") + } + if c.GatewayURL == nil || *c.GatewayURL == "" { + return errors.New("gateway_url must be set") + } + if !net.IsValidURL(*c.GatewayURL) { + return errors.New("gateway_url must be a valid URL") + } + if c.Receiver == nil || *c.Receiver == "" { + return errors.New("receiver must be set") + } + if !common.IsHexAddress(*c.Receiver) { + return errors.New("receiver must be a valid address") + } + return nil +} + +type Performance struct { + RPS *int64 `toml:"rps"` + RequestsPerCall *uint32 `toml:"requests_per_call"` + Duration *blockchain.StrDuration `toml:"duration"` +} + +func (c *Performance) Validate() error { + if c.RPS == nil || *c.RPS < 1 { + return errors.New("rps must be greater than 0") + } + if c.RequestsPerCall != nil && *c.RequestsPerCall < 1 { + return errors.New("requests_per_call must be greater than 0") + } + if c.Duration == nil || c.Duration.Duration < 1 { + return errors.New("duration must be greater than 0") + } + return nil +} + +func (c *Config) Validate() error { + if c == nil { + return nil + } + if c.Common != nil { + if err := c.Common.Validate(); err != nil { + return err + } + } + if c.Performance != nil { + if err := c.Performance.Validate(); err != nil { + return err + } + } + + return nil +} diff --git a/integration-tests/testconfig/functions/example.toml b/integration-tests/testconfig/functions/example.toml new file mode 100644 index 00000000000..7628fbeee32 --- /dev/null +++ b/integration-tests/testconfig/functions/example.toml @@ -0,0 +1,113 @@ +# Example of full config with all fields +# General part +[ChainlinkImage] +image="public.ecr.aws/chainlink/chainlink" +version="2.7.0" + +[Logging] +# if set to true will save logs even if test did not fail +test_log_collect=false + +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth="loki-basic-auth" +# only needed for cloud grafana +bearer_token="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +bearer_token="my-awesome-token" + +# if you want to use simulated network +[Network] +selected_networks=["polygon_mumbai"] + +[Network.RpcHttpUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.RpcWsUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.WalletKeys] +polygon_mumbai = ["change-me-to-your-PK"] + +[PrivateEthereumNetwork] +# pos or pow +consensus_type="pos" +# only prysm supported currently +consensus_layer="prysm" +# geth, besu, nethermind or erigon +execution_layer="geth" +# if true after env started it will wait for at least 1 epoch to be finalised before continuing +wait_for_finalization=false + +[PrivateEthereumNetwork.EthereumChainConfig] +# duration of single slot, lower => faster block production, must be >= 4 +seconds_per_slot=12 +# numer of slots in epoch, lower => faster epoch finalisation, must be >= 4 +slots_per_epoch=6 +# extra genesis gelay, no need to modify, but it should be after all validators/beacon chain starts +genesis_delay=15 +# number of validators in the network +validator_count=8 +chain_id=1337 +# list of addresses to be prefunded in genesis +addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] + +# Common +[Common] +chainlink_node_funding = 0.5 + +# Product part +[Functions] +[Functions.Common] +# Polygon Mumbai only for now +receiver = "0x3098B6665589959711A48a6bAe5B7F2908f6a3bE" +don_id = "fun-staging-mumbai-1" +gateway_url = "https://gateway-stg-one.main.stage.cldev.sh" +link_token_addr = "0x326C977E6efc84E512bB9C30f76E30c160eD06FB" +coordinator_addr = "0x6D6a83BB356b7242E88C1A2b290102fde26590D0" +router_addr = "0x2673266D3Cd08b53494B5a92B66DEec7F1408E7A" + +# comment "client_addr" and "subscription_id" and test will create a new pair +# get it from logs and save +client_addr = "0x89D4b58D859a536D0B888ecD5093eF5FF9e4F977" +subscription_id = 47 +sub_funds = 10 + +functions_call_payload_with_secrets = "return Functions.encodeString(JSON.stringify(secrets))" +functions_call_payload_http = """ +const response = await Functions.makeHttpRequest({ url: 'http://dummyjson.com/products/1' }); +return Functions.encodeUint256(response.data.id); +""" +functions_call_payload_real = """ +const arg1 = args[0]; +const arg2 = args[1]; +const arg3 = args[2]; +const arg4 = args[3]; + +const response = await Functions.makeHttpRequest({ url: 'http://dummyjson.com/products/${arg1}' }); +return Functions.encodeString(JSON.stringify(secrets)); +""" +secrets_slot_id = 0 +secrets_version_id = 1693945705 + +[Functions.Performance] +rps = 95 +requests_per_call = 20 +duration = "10m" \ No newline at end of file diff --git a/integration-tests/load/functions/config.toml b/integration-tests/testconfig/functions/functions.toml similarity index 63% rename from integration-tests/load/functions/config.toml rename to integration-tests/testconfig/functions/functions.toml index 2de3ba9282c..a4bcb6439e4 100644 --- a/integration-tests/load/functions/config.toml +++ b/integration-tests/testconfig/functions/functions.toml @@ -1,42 +1,6 @@ -[Soak] -rps = 1 -requests_per_call = 40 -duration = "10m" - -[Stress] -rps = 1 -requests_per_call = 78 -duration = "10m" - -[SecretsSoak] -rps = 1 -requests_per_call = 20 -duration = "10m" - -[SecretsStress] -rps = 1 -requests_per_call = 40 -duration = "10m" - -[RealSoak] -rps = 1 -requests_per_call = 20 -duration = "10m" - -[RealStress] -rps = 1 -requests_per_call = 40 -duration = "10m" - -[GatewayListSoak] -rps = 95 -duration = "10m" - -[GatewaySetSoak] -rps = 95 -duration = "10m" - -[Common] +# product defaults +[Functions] +[Functions.Common] # Polygon Mumbai only for now receiver = "0x3098B6665589959711A48a6bAe5B7F2908f6a3bE" don_id = "fun-staging-mumbai-1" @@ -66,8 +30,62 @@ const response = await Functions.makeHttpRequest({ url: 'http://dummyjson.com/pr return Functions.encodeString(JSON.stringify(secrets)); """ secrets_slot_id = 0 -secrets_version = 1693945705 +secrets_version_id = 1693945705 # uncomment to upload new secrets to s4 and use it in your run # TODO: not working now -#secrets = "{\"secrets\": \"secretValue\"}" \ No newline at end of file +#secrets = "{\"secrets\": \"secretValue\"}" + +# gateway-list specific test configuration +[GatewayList.Functions] +[GatewayList.Functions.Performance] +rps = 95 +duration = "10m" + +# gateway-set specific test configuration +[GatewaySet.Functions] +[GatewaySet.Functions.Performance] +rps = 95 +duration = "10m" + +# real-soak specific test configuration +[RealSoak.Functions] +[RealSoak.Functions.Performance] +rps = 1 +requests_per_call = 20 +duration = "10m" + +# real-stress specific test configuration +[RealStress.Functions] +[RealStress.Functions.Performance] +rps = 1 +requests_per_call = 40 +duration = "10m" + +# secrets-soak specific test configuration +[SecretsSoak.Functions] +[SecretsSoak.Functions.Performance] +rps = 1 +requests_per_call = 20 +duration = "10m" + +# secrets-stress specific test configuration +[SecretsStress.Functions] +[SecretsStress.Functions.Performance] +rps = 1 +requests_per_call = 40 +duration = "10m" + +# soak specific test configuration +[Soak.Functions] +[Soak.Functions.Performance] +rps = 1 +requests_per_call = 40 +duration = "10m" + +# soak specific test configuration +[Stress.Functions] +[Stress.Functions.Performance] +rps = 1 +requests_per_call = 78 +duration = "10m" \ No newline at end of file diff --git a/integration-tests/testconfig/keeper/config.go b/integration-tests/testconfig/keeper/config.go new file mode 100644 index 00000000000..da6cd7acc98 --- /dev/null +++ b/integration-tests/testconfig/keeper/config.go @@ -0,0 +1,85 @@ +package keeper + +import ( + "errors" +) + +type Config struct { + Common *Common `toml:"Common"` +} + +func (c *Config) Validate() error { + if c.Common == nil { + return nil + } + return c.Common.Validate() +} + +type Common struct { + RegistryToTest *string `toml:"registry_to_test"` + NumberOfRegistries *int `toml:"number_of_registries"` + NumberOfNodes *int `toml:"number_of_nodes"` + NumberOfUpkeeps *int `toml:"number_of_upkeeps"` + UpkeepGasLimit *int64 `toml:"upkeep_gas_limit"` + CheckGasToBurn *int64 `toml:"check_gas_to_burn"` + PerformGasToBurn *int64 `toml:"perform_gas_to_burn"` + MaxPerformGas *int64 `toml:"max_perform_gas"` + BlockRange *int64 `toml:"block_range"` + BlockInterval *int64 `toml:"block_interval"` + ForceSingleTxKey *bool `toml:"forces_single_tx_key"` + DeleteJobsOnEnd *bool `toml:"delete_jobs_on_end"` + RegistryAddress *string `toml:"registry_address"` + RegistrarAddress *string `toml:"registrar_address"` + LinkTokenAddress *string `toml:"link_token_address"` + EthFeedAddress *string `toml:"eth_feed_address"` + GasFeedAddress *string `toml:"gas_feed_address"` +} + +func (c *Common) Validate() error { + if c.RegistryToTest == nil || *c.RegistryToTest == "" { + return errors.New("registry_to_test must be set") + } + if c.NumberOfRegistries == nil || *c.NumberOfRegistries <= 0 { + return errors.New("number_of_registries must be a positive integer") + } + if c.NumberOfNodes == nil || *c.NumberOfNodes <= 0 { + return errors.New("number_of_nodes must be a positive integer") + } + if c.NumberOfUpkeeps == nil || *c.NumberOfUpkeeps <= 0 { + return errors.New("number_of_upkeeps must be a positive integer") + } + if c.UpkeepGasLimit == nil || *c.UpkeepGasLimit <= 0 { + return errors.New("upkeep_gas_limit must be a positive integer") + } + if c.CheckGasToBurn == nil || *c.CheckGasToBurn <= 0 { + return errors.New("check_gas_to_burn must be a positive integer") + } + if c.PerformGasToBurn == nil || *c.PerformGasToBurn <= 0 { + return errors.New("perform_gas_to_burn must be a positive integer") + } + if c.MaxPerformGas == nil || *c.MaxPerformGas <= 0 { + return errors.New("max_perform_gas must be a positive integer") + } + if c.BlockRange == nil || *c.BlockRange <= 0 { + return errors.New("block_range must be a positive integer") + } + if c.BlockInterval == nil || *c.BlockInterval <= 0 { + return errors.New("block_interval must be a positive integer") + } + if c.RegistryAddress == nil { + c.RegistryAddress = new(string) + } + if c.RegistrarAddress == nil { + c.RegistrarAddress = new(string) + } + if c.LinkTokenAddress == nil { + c.LinkTokenAddress = new(string) + } + if c.EthFeedAddress == nil { + c.EthFeedAddress = new(string) + } + if c.GasFeedAddress == nil { + c.GasFeedAddress = new(string) + } + return nil +} diff --git a/integration-tests/testconfig/keeper/example.toml b/integration-tests/testconfig/keeper/example.toml new file mode 100644 index 00000000000..6bdd6537bc3 --- /dev/null +++ b/integration-tests/testconfig/keeper/example.toml @@ -0,0 +1,88 @@ +# Example of full config with all fields +# General part +[ChainlinkImage] +image="public.ecr.aws/chainlink/chainlink" +version="2.7.0" + +[Logging] +# if set to true will save logs even if test did not fail +test_log_collect=false + +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth="loki-basic-auth" +# only needed for cloud grafana +bearer_token="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +bearer_token="my-awesome-token" + +# if you want to use polygon_mumbial +[Network] +selected_networks=["polygon_mumbai"] + +[Network.RpcHttpUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.RpcWsUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.WalletKeys] +polygon_mumbai = ["change-me-to-your-PK"] + +[PrivateEthereumNetwork] +# pos or pow +consensus_type="pos" +# only prysm supported currently +consensus_layer="prysm" +# geth, besu, nethermind or erigon +execution_layer="geth" +# if true after env started it will wait for at least 1 epoch to be finalised before continuing +wait_for_finalization=false + +[PrivateEthereumNetwork.EthereumChainConfig] +# duration of single slot, lower => faster block production, must be >= 4 +seconds_per_slot=12 +# numer of slots in epoch, lower => faster epoch finalisation, must be >= 4 +slots_per_epoch=6 +# extra genesis gelay, no need to modify, but it should be after all validators/beacon chain starts +genesis_delay=15 +# number of validators in the network +validator_count=8 +chain_id=1337 +# list of addresses to be prefunded in genesis +addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] + +# Product part +[Common] +chainlink_node_funding = 0.5 + +[Keeper.Common] +registry_to_test = "2_1" +number_of_registries = 1 +number_of_nodes = 6 +number_of_upkeeps = 500 +upkeep_gas_limit = 150000 +check_gas_to_burn = 100000 +perform_gas_to_burn = 50000 +max_perform_gas = 5000000 +block_range = 3600 +block_interval = 20 +forces_single_tx_key = false +delete_jobs_on_end = true \ No newline at end of file diff --git a/integration-tests/testconfig/keeper/keeper.toml b/integration-tests/testconfig/keeper/keeper.toml new file mode 100644 index 00000000000..516dbb35a63 --- /dev/null +++ b/integration-tests/testconfig/keeper/keeper.toml @@ -0,0 +1,17 @@ +# product defaults +[Common] +chainlink_node_funding = 0.5 + +[Keeper.Common] +registry_to_test = "2_1" +number_of_registries = 1 +number_of_nodes = 6 +number_of_upkeeps = 500 +upkeep_gas_limit = 1500000 +check_gas_to_burn = 100000 +perform_gas_to_burn = 50000 +max_perform_gas = 5000000 +block_range = 3600 +block_interval = 20 +forces_single_tx_key = false +delete_jobs_on_end = true \ No newline at end of file diff --git a/integration-tests/testconfig/log_poller/config.go b/integration-tests/testconfig/log_poller/config.go new file mode 100644 index 00000000000..96c3b55c276 --- /dev/null +++ b/integration-tests/testconfig/log_poller/config.go @@ -0,0 +1,158 @@ +package logpoller + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi" + + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" +) + +const ( + ErrReadPerfConfig = "failed to read TOML config for performance tests" + ErrUnmarshalPerfConfig = "failed to unmarshal TOML config for performance tests" +) + +type GeneratorType = string + +const ( + GeneratorType_WASP = "wasp" + GeneratorType_Looped = "looped" +) + +type Config struct { + General *General `toml:"General"` + ChaosConfig *ChaosConfig `toml:"Chaos"` + Wasp *WaspConfig `toml:"Wasp"` + LoopedConfig *LoopedConfig `toml:"Looped"` +} + +func (c *Config) Validate() error { + if c.General == nil { + return fmt.Errorf("General config must be set") + } + + err := c.General.Validate() + if err != nil { + return fmt.Errorf("General config validation failed: %w", err) + } + + switch *c.General.Generator { + case GeneratorType_WASP: + if c.Wasp == nil { + return fmt.Errorf("wasp config is nil") + } + err = c.Wasp.Validate() + if err != nil { + return fmt.Errorf("wasp config validation failed: %w", err) + } + case GeneratorType_Looped: + if c.LoopedConfig == nil { + return fmt.Errorf("looped config is nil") + } + err = c.LoopedConfig.Validate() + if err != nil { + return fmt.Errorf("looped config validation failed: %w", err) + } + default: + return fmt.Errorf("unknown generator type: %s", *c.General.Generator) + } + + if c.ChaosConfig != nil { + if err := c.ChaosConfig.Validate(); err != nil { + return fmt.Errorf("chaos config validation failed: %w", err) + } + } + + return nil +} + +type LoopedConfig struct { + ExecutionCount *int `toml:"execution_count"` + MinEmitWaitTimeMs *int `toml:"min_emit_wait_time_ms"` + MaxEmitWaitTimeMs *int `toml:"max_emit_wait_time_ms"` +} + +func (l *LoopedConfig) Validate() error { + if l.ExecutionCount == nil || *l.ExecutionCount == 0 { + return fmt.Errorf("execution_count must be set and > 0") + } + + if l.MinEmitWaitTimeMs == nil || *l.MinEmitWaitTimeMs == 0 { + return fmt.Errorf("min_emit_wait_time_ms must be set and > 0") + } + + if l.MaxEmitWaitTimeMs == nil || *l.MaxEmitWaitTimeMs == 0 { + return fmt.Errorf("max_emit_wait_time_ms must be set and > 0") + } + + return nil +} + +type General struct { + Generator *string `toml:"generator"` + EventsToEmit []abi.Event `toml:"-"` + Contracts *int `toml:"contracts"` + EventsPerTx *int `toml:"events_per_tx"` + UseFinalityTag *bool `toml:"use_finality_tag"` +} + +func (g *General) Validate() error { + if g.Generator == nil || *g.Generator == "" { + return fmt.Errorf("generator is empty") + } + + if g.Contracts == nil || *g.Contracts == 0 { + return fmt.Errorf("contracts is 0, but must be > 0") + } + + if g.EventsPerTx == nil || *g.EventsPerTx == 0 { + return fmt.Errorf("events_per_tx is 0, but must be > 0") + } + + return nil +} + +type ChaosConfig struct { + ExperimentCount *int `toml:"experiment_count"` + TargetComponent *string `toml:"target_component"` +} + +func (c *ChaosConfig) Validate() error { + if c.ExperimentCount != nil && *c.ExperimentCount == 0 { + return fmt.Errorf("experiment_count must be > 0") + } + + return nil +} + +type WaspConfig struct { + RPS *int64 `toml:"rps"` + LPS *int64 `toml:"lps"` + RateLimitUnitDuration *blockchain.StrDuration `toml:"rate_limit_unit_duration"` + Duration *blockchain.StrDuration `toml:"duration"` + CallTimeout *blockchain.StrDuration `toml:"call_timeout"` +} + +func (w *WaspConfig) Validate() error { + if w.RPS == nil && w.LPS == nil { + return fmt.Errorf("either RPS or LPS needs to be set") + } + if *w.RPS == 0 && *w.LPS == 0 { + return fmt.Errorf("either RPS or LPS needs to be a positive integer") + } + if *w.RPS != 0 && *w.LPS != 0 { + return fmt.Errorf("only one of RPS or LPS can be set") + } + if w.Duration == nil || w.Duration.Duration == 0 { + return fmt.Errorf("duration must be set and > 0") + } + if w.CallTimeout == nil || w.CallTimeout.Duration == 0 { + return fmt.Errorf("call_timeout must be set and > 0") + } + if w.RateLimitUnitDuration == nil || w.RateLimitUnitDuration.Duration == 0 { + return fmt.Errorf("rate_limit_unit_duration must be set and > 0") + } + + return nil +} diff --git a/integration-tests/testconfig/log_poller/example.toml b/integration-tests/testconfig/log_poller/example.toml new file mode 100644 index 00000000000..90ec89a3ed1 --- /dev/null +++ b/integration-tests/testconfig/log_poller/example.toml @@ -0,0 +1,87 @@ +# Example of full config with all fields +# General part +[ChainlinkImage] +image="public.ecr.aws/chainlink/chainlink" +version="2.7.0" + +[Logging] +# if set to true will save logs even if test did not fail +test_log_collect=false + +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth="loki-basic-auth" +# only needed for cloud grafana +bearer_token="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +bearer_token="my-awesome-token" + +# if you want to use polygon_mumbial +[Network] +selected_networks=["polygon_mumbai"] + +[Network.RpcHttpUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.RpcWsUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.WalletKeys] +polygon_mumbai = ["change-me-to-your-PK"] + +[PrivateEthereumNetwork] +# pos or pow +consensus_type="pos" +# only prysm supported currently +consensus_layer="prysm" +# geth, besu, nethermind or erigon +execution_layer="geth" +# if true after env started it will wait for at least 1 epoch to be finalised before continuing +wait_for_finalization=false + +[PrivateEthereumNetwork.EthereumChainConfig] +# duration of single slot, lower => faster block production, must be >= 4 +seconds_per_slot=12 +# numer of slots in epoch, lower => faster epoch finalisation, must be >= 4 +slots_per_epoch=6 +# extra genesis gelay, no need to modify, but it should be after all validators/beacon chain starts +genesis_delay=15 +# number of validators in the network +validator_count=8 +chain_id=1337 +# list of addresses to be prefunded in genesis +addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] + +# Common +[Common] +chainlink_node_funding = 0.5 + +# Product part +[LogPoller] +[LogPoller.General] +generator = "looped" +contracts = 2 +events_per_tx = 4 +use_finality_tag = true + +[LogPoller.Looped] +execution_count = 100 +min_emit_wait_time_ms = 200 +max_emit_wait_time_ms = 500 \ No newline at end of file diff --git a/integration-tests/testconfig/log_poller/log_poller.toml b/integration-tests/testconfig/log_poller/log_poller.toml new file mode 100644 index 00000000000..2f46ebf11c2 --- /dev/null +++ b/integration-tests/testconfig/log_poller/log_poller.toml @@ -0,0 +1,61 @@ +# product defaults +[LogPoller] +[LogPoller.General] +generator = "looped" +contracts = 2 +events_per_tx = 4 +use_finality_tag = true + +[LogPoller.Looped] +execution_count = 100 +min_emit_wait_time_ms = 200 +max_emit_wait_time_ms = 500 + +# test-specific +[TestLogPollerFewFiltersFixedDepth.LogPoller.General] +use_finality_tag = false + +[TestLogManyFiltersPollerFinalityTag.LogPoller.General] +contracts = 300 +events_per_tx = 3 + +[TestLogManyFiltersPollerFinalityTag.LogPoller.Looped] +execution_count = 30 + +[TestLogManyFiltersPollerFixedDepth.LogPoller.General] +use_finality_tag = false +contracts = 300 +events_per_tx = 3 + +[TestLogManyFiltersPollerFixedDepth.LogPoller.Looped] +execution_count = 30 + +[TestLogPollerWithChaosFinalityTag.LogPoller.General] +execution_count = 30 +[TestLogPollerWithChaosFinalityTag.LogPoller.Chaos] +experiment_count = 4 +target_component = "chainlink" + +[TestLogPollerWithChaosFixedDepth.LogPoller.General] +execution_count = 30 +use_finality_tag = false +[TestLogPollerWithChaosFixedDepth.LogPoller.Chaos] +experiment_count = 4 +target_component = "chainlink" + +[TestLogPollerWithChaosPostgresFinalityTag.LogPoller.General] +execution_count = 30 +[TestLogPollerWithChaosPostgresFinalityTag.LogPoller.Chaos] +experiment_count = 4 +target_component = "postgres" + +[TestLogPollerWithChaosPostgresFixedDepth.LogPoller.General] +execution_count = 30 +use_finality_tag = false +[TestLogPollerWithChaosPostgresFixedDepth.LogPoller.Chaos] +experiment_count = 4 +target_component = "postgres" + +[TestLogPollerReplayFixedDepth.LogPoller.General] +use_finality_tag = false + diff --git a/integration-tests/testconfig/node/example.toml b/integration-tests/testconfig/node/example.toml new file mode 100644 index 00000000000..55ee1ffccf1 --- /dev/null +++ b/integration-tests/testconfig/node/example.toml @@ -0,0 +1,79 @@ +# Example of full config with all fields +# General part +[ChainlinkImage] +image="public.ecr.aws/chainlink/chainlink" +version="2.7.0" + +[Logging] +# if set to true will save logs even if test did not fail +test_log_collect=false + +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth="loki-basic-auth" +# only needed for cloud grafana +bearer_token="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +bearer_token="my-awesome-token" + +# if you want to use polygon_mumbial +[Network] +selected_networks=["polygon_mumbai"] + +[Network.RpcHttpUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.RpcWsUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.WalletKeys] +polygon_mumbai = ["change-me-to-your-PK"] + +[PrivateEthereumNetwork] +# pos or pow +consensus_type="pos" +# only prysm supported currently +consensus_layer="prysm" +# geth, besu, nethermind or erigon +execution_layer="geth" +# if true after env started it will wait for at least 1 epoch to be finalised before continuing +wait_for_finalization=false + +[PrivateEthereumNetwork.EthereumChainConfig] +# duration of single slot, lower => faster block production, must be >= 4 +seconds_per_slot=12 +# numer of slots in epoch, lower => faster epoch finalisation, must be >= 4 +slots_per_epoch=6 +# extra genesis gelay, no need to modify, but it should be after all validators/beacon chain starts +genesis_delay=15 +# number of validators in the network +validator_count=8 +chain_id=1337 +# list of addresses to be prefunded in genesis +addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] + +# Common +[Common] +chainlink_node_funding = 0.5 + +# Test-specific part +[ChainlinkUpgradeImage] +image="public.ecr.aws/chainlink/chainlink" +version="2.8.0" \ No newline at end of file diff --git a/integration-tests/testconfig/node/node.toml b/integration-tests/testconfig/node/node.toml new file mode 100644 index 00000000000..683b55a35a1 --- /dev/null +++ b/integration-tests/testconfig/node/node.toml @@ -0,0 +1,5 @@ +# original image +[ChainlinkImage] + +# image to upgrade to +[ChainlinkUpgradeImage] \ No newline at end of file diff --git a/integration-tests/testconfig/ocr/example.toml b/integration-tests/testconfig/ocr/example.toml new file mode 100644 index 00000000000..6cbdbef1555 --- /dev/null +++ b/integration-tests/testconfig/ocr/example.toml @@ -0,0 +1,96 @@ +# Example of full config with all fields +# General part +[ChainlinkImage] +image="public.ecr.aws/chainlink/chainlink" +version="2.7.0" + +[Logging] +# if set to true will save logs even if test did not fail +test_log_collect=false + +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth="loki-basic-auth" +# only needed for cloud grafana +bearer_token="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +bearer_token="my-awesome-token" + +# if you want to use polygon_mumbial +[Network] +selected_networks=["polygon_mumbai"] + +[Network.RpcHttpUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.RpcWsUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.WalletKeys] +polygon_mumbai = ["change-me-to-your-PK"] + +[PrivateEthereumNetwork] +# pos or pow +consensus_type="pos" +# only prysm supported currently +consensus_layer="prysm" +# geth, besu, nethermind or erigon +execution_layer="geth" +# if true after env started it will wait for at least 1 epoch to be finalised before continuing +wait_for_finalization=false + +[PrivateEthereumNetwork.EthereumChainConfig] +# duration of single slot, lower => faster block production, must be >= 4 +seconds_per_slot=12 +# numer of slots in epoch, lower => faster epoch finalisation, must be >= 4 +slots_per_epoch=6 +# extra genesis gelay, no need to modify, but it should be after all validators/beacon chain starts +genesis_delay=15 +# number of validators in the network +validator_count=8 +chain_id=1337 +# list of addresses to be prefunded in genesis +addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] + +# load test specific configuration +[Load.OCR] +[Load.OCR.Common] +eth_funds = 3 + +[Load.OCR.Load] +test_duration = "3m" +rate_limit_unit_duration = "1m" +rate = 3 +verification_interval = "5s" +verification_timeout = "3m" +ea_change_interval = "5s" + +# soak test specific configuration +[Soak.Common] +chainlink_node_funding = 100 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration="15m" + +[Soak.OCR.Soak] +ocr_version="1" +number_of_contracts=2 +time_between_rounds="1m" \ No newline at end of file diff --git a/integration-tests/testconfig/ocr/ocr.go b/integration-tests/testconfig/ocr/ocr.go new file mode 100644 index 00000000000..0fd995a96f1 --- /dev/null +++ b/integration-tests/testconfig/ocr/ocr.go @@ -0,0 +1,136 @@ +package ocr + +import ( + "errors" + + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" +) + +type Config struct { + Soak *SoakConfig `toml:"Soak"` + Load *Load `toml:"Load"` + Volume *Volume `toml:"Volume"` + Common *Common `toml:"Common"` +} + +func (o *Config) Validate() error { + if o.Common != nil { + if err := o.Common.Validate(); err != nil { + return err + } + } + if o.Soak != nil { + if err := o.Soak.Validate(); err != nil { + return err + } + } + if o.Volume != nil { + if err := o.Volume.Validate(); err != nil { + return err + } + } + return nil +} + +type Common struct { + ETHFunds *int `toml:"eth_funds"` + TestDuration *blockchain.StrDuration `toml:"test_duration"` +} + +func (o *Common) Validate() error { + if o.ETHFunds != nil && *o.ETHFunds < 0 { + return errors.New("eth_funds must be set and cannot be negative") + } + return nil +} + +type Load struct { + Rate *int64 `toml:"rate"` + RequestsPerUnit *int `toml:"requests_per_unit"` + RateLimitUnitDuration *blockchain.StrDuration `toml:"rate_limit_unit_duration"` + VerificationInterval *blockchain.StrDuration `toml:"verification_interval"` + VerificationTimeout *blockchain.StrDuration `toml:"verification_timeout"` + EAChangeInterval *blockchain.StrDuration `toml:"ea_change_interval"` + TestDuration *blockchain.StrDuration `toml:"test_duration"` +} + +func (o *Load) Validate() error { + if o.TestDuration == nil { + return errors.New("load test duration must be set") + } + if o.Rate == nil || *o.Rate <= 0 { + return errors.New("rate must be set and be a positive integer") + } + if o.RequestsPerUnit == nil || *o.RequestsPerUnit <= 0 { + return errors.New("vu_requests_per_unit must be set and be a positive integer") + } + if o.RateLimitUnitDuration == nil || o.RateLimitUnitDuration.Duration == 0 { + return errors.New("rate_limit_unit_duration must be set and be a positive integer") + } + if o.VerificationInterval == nil || o.VerificationInterval.Duration == 0 { + return errors.New("verification_interval must be set and be a positive integer") + } + if o.VerificationTimeout == nil || o.VerificationTimeout.Duration == 0 { + return errors.New("verification_timeout must be set and be a positive integer") + } + if o.EAChangeInterval == nil || o.EAChangeInterval.Duration == 0 { + return errors.New("ea_change_interval must be set and be a positive integer") + } + + return nil +} + +type Volume struct { + Rate *int64 `toml:"rate"` + VURequestsPerUnit *int `toml:"vu_requests_per_unit"` + RateLimitUnitDuration *blockchain.StrDuration `toml:"rate_limit_unit_duration"` + VerificationInterval *blockchain.StrDuration `toml:"verification_interval"` + VerificationTimeout *blockchain.StrDuration `toml:"verification_timeout"` + EAChangeInterval *blockchain.StrDuration `toml:"ea_change_interval"` + TestDuration *blockchain.StrDuration `toml:"test_duration"` +} + +func (o *Volume) Validate() error { + if o.TestDuration == nil { + return errors.New("volume test duration must be set") + } + if o.Rate == nil || *o.Rate <= 0 { + return errors.New("rate must be set and be a positive integer") + } + if o.VURequestsPerUnit == nil || *o.VURequestsPerUnit <= 0 { + return errors.New("vu_requests_per_unit must be set and be a positive integer") + } + if o.RateLimitUnitDuration == nil || o.RateLimitUnitDuration.Duration == 0 { + return errors.New("rate_limit_unit_duration must be set and be a positive integer") + } + if o.VerificationInterval == nil || o.VerificationInterval.Duration == 0 { + return errors.New("verification_interval must be set and be a positive integer") + } + if o.VerificationTimeout == nil || o.VerificationTimeout.Duration == 0 { + return errors.New("verification_timeout must be set and be a positive integer") + } + if o.EAChangeInterval == nil || o.EAChangeInterval.Duration == 0 { + return errors.New("ea_change_interval must be set and be a positive integer") + } + + return nil +} + +type SoakConfig struct { + OCRVersion *string `toml:"ocr_version"` + NumberOfContracts *int `toml:"number_of_contracts"` + TimeBetweenRounds *blockchain.StrDuration `toml:"time_between_rounds"` +} + +func (o *SoakConfig) Validate() error { + if o.OCRVersion == nil || *o.OCRVersion == "" { + return errors.New("ocr_version must be set to either 1 or 2") + } + if o.NumberOfContracts == nil || *o.NumberOfContracts <= 1 { + return errors.New("number_of_contracts must be set and be greater than 1") + } + if o.TimeBetweenRounds == nil || o.TimeBetweenRounds.Duration == 0 { + return errors.New("time_between_rounds must be set and be a positive integer") + } + return nil +} diff --git a/integration-tests/testconfig/ocr/ocr.toml b/integration-tests/testconfig/ocr/ocr.toml new file mode 100644 index 00000000000..8d3c73ca761 --- /dev/null +++ b/integration-tests/testconfig/ocr/ocr.toml @@ -0,0 +1,43 @@ +# product defaults +[Common] +chainlink_node_funding = 0.5 + +# load test specific configuration +[Load.OCR] +[Load.OCR.Common] +eth_funds = 3 + +[Load.OCR.Load] +test_duration = "3m" +rate_limit_unit_duration = "1m" +rate = 3 +verification_interval = "5s" +verification_timeout = "3m" +ea_change_interval = "5s" + +# volume test specific configuration +[Volume.OCR] +[Volume.OCR.Common] +eth_funds = 3 + +[Volume.OCR.Volume] +test_duration = "3m" +rate_limit_unit_duration = "1m" +vu_requests_per_unit = 10 +rate = 1 +verification_interval = "5s" +verification_timeout = "3m" +ea_change_interval = "5s" + +# soak test specific configuration +[Soak.Common] +chainlink_node_funding = 100 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration="15m" + +[Soak.OCR.Soak] +ocr_version="1" +number_of_contracts=2 +time_between_rounds="1m" \ No newline at end of file diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go new file mode 100644 index 00000000000..c80202bf45c --- /dev/null +++ b/integration-tests/testconfig/testconfig.go @@ -0,0 +1,540 @@ +package testconfig + +import ( + "embed" + "encoding/base64" + "fmt" + "os" + "slices" + "strings" + + "github.com/barkimedes/go-deepcopy" + "github.com/google/uuid" + "github.com/pelletier/go-toml/v2" + "github.com/pkg/errors" + "github.com/rs/zerolog" + "golang.org/x/text/cases" + "golang.org/x/text/language" + + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + k8s_config "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" + "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" + a_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" + f_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/functions" + keeper_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/keeper" + lp_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/log_poller" + ocr_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ocr" + vrf_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrf" + vrfv2_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2" + vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" +) + +type GlobalTestConfig interface { + GetChainlinkImageConfig() *ctf_config.ChainlinkImageConfig + GetLoggingConfig() *ctf_config.LoggingConfig + GetNetworkConfig() *ctf_config.NetworkConfig + GetPrivateEthereumNetworkConfig() *test_env.EthereumNetwork + GetPyroscopeConfig() *ctf_config.PyroscopeConfig +} + +type UpgradeableChainlinkTestConfig interface { + GetChainlinkUpgradeImageConfig() *ctf_config.ChainlinkImageConfig +} + +type CommonTestConfig interface { + GetCommonConfig() *Common +} + +type VRFv2TestConfig interface { + GetVRFv2Config() *vrfv2_config.Config +} + +type VRFv2PlusTestConfig interface { + GetVRFv2PlusConfig() *vrfv2plus_config.Config +} + +type FunctionsTestConfig interface { + GetFunctionsConfig() *f_config.Config +} + +type KeeperTestConfig interface { + GetKeeperConfig() *keeper_config.Config +} + +type OcrTestConfig interface { + GetOCRConfig() *ocr_config.Config +} + +type NamedConfiguration interface { + GetConfigurationName() string +} + +type TestConfig struct { + ChainlinkImage *ctf_config.ChainlinkImageConfig `toml:"ChainlinkImage"` + ChainlinkUpgradeImage *ctf_config.ChainlinkImageConfig `toml:"ChainlinkUpgradeImage"` + Logging *ctf_config.LoggingConfig `toml:"Logging"` + Network *ctf_config.NetworkConfig `toml:"Network"` + Pyroscope *ctf_config.PyroscopeConfig `toml:"Pyroscope"` + PrivateEthereumNetwork *ctf_test_env.EthereumNetwork `toml:"PrivateEthereumNetwork"` + + Common *Common `toml:"Common"` + Automation *a_config.Config `toml:"Automation"` + Functions *f_config.Config `toml:"Functions"` + Keeper *keeper_config.Config `toml:"Keeper"` + LogPoller *lp_config.Config `toml:"LogPoller"` + OCR *ocr_config.Config `toml:"OCR"` + VRF *vrf_config.Config `toml:"VRF"` + VRFv2 *vrfv2_config.Config `toml:"VRFv2"` + VRFv2Plus *vrfv2plus_config.Config `toml:"VRFv2Plus"` + + ConfigurationName string `toml:"-"` +} + +var embeddedConfigs embed.FS +var areConfigsEmbedded bool + +func init() { + embeddedConfigs = embeddedConfigsFs +} + +// Returns Grafana URL from Logging config +func (c *TestConfig) GetGrafanaBaseURL() (string, error) { + if c.Logging.Grafana == nil || c.Logging.Grafana.BaseUrl == nil { + return "", errors.New("grafana base url not set") + } + + return strings.TrimSuffix(*c.Logging.Grafana.BaseUrl, "/"), nil +} + +// Returns Grafana Dashboard URL from Logging config +func (c *TestConfig) GetGrafanaDashboardURL() (string, error) { + if c.Logging.Grafana == nil || c.Logging.Grafana.DashboardUrl == nil { + return "", errors.New("grafana dashboard url not set") + } + + url := *c.Logging.Grafana.DashboardUrl + if !strings.HasPrefix(url, "/") { + url = "/" + url + } + + return url, nil +} + +// Saves Test Config to a local file +func (c *TestConfig) Save() (string, error) { + filePath := fmt.Sprintf("test_config-%s.toml", uuid.New()) + + content, err := toml.Marshal(*c) + if err != nil { + return "", errors.Wrapf(err, "error marshaling test config") + } + + err = os.WriteFile(filePath, content, 0600) + if err != nil { + return "", errors.Wrapf(err, "error writing test config") + } + + return filePath, nil +} + +// MustCopy Returns a deep copy of the Test Config or panics on error +func (c TestConfig) MustCopy() any { + return deepcopy.MustAnything(c).(TestConfig) +} + +// MustCopy Returns a deep copy of struct passed to it and returns a typed copy (or panics on error) +func MustCopy[T any](c T) T { + return deepcopy.MustAnything(c).(T) +} + +func (c *TestConfig) GetLoggingConfig() *ctf_config.LoggingConfig { + return c.Logging +} + +func (c TestConfig) GetNetworkConfig() *ctf_config.NetworkConfig { + return c.Network +} + +func (c TestConfig) GetChainlinkImageConfig() *ctf_config.ChainlinkImageConfig { + return c.ChainlinkImage +} + +func (c TestConfig) GetPrivateEthereumNetworkConfig() *ctf_test_env.EthereumNetwork { + return c.PrivateEthereumNetwork +} + +func (c TestConfig) GetPyroscopeConfig() *ctf_config.PyroscopeConfig { + return c.Pyroscope +} + +func (c TestConfig) GetCommonConfig() *Common { + return c.Common +} + +func (c TestConfig) GetVRFv2Config() *vrfv2_config.Config { + return c.VRFv2 +} + +func (c TestConfig) GetFunctionsConfig() *f_config.Config { + return c.Functions +} + +func (c TestConfig) GetVRFv2PlusConfig() *vrfv2plus_config.Config { + return c.VRFv2Plus +} + +func (c TestConfig) GetChainlinkUpgradeImageConfig() *ctf_config.ChainlinkImageConfig { + return c.ChainlinkUpgradeImage +} + +func (c TestConfig) GetKeeperConfig() *keeper_config.Config { + return c.Keeper +} + +func (c TestConfig) GetOCRConfig() *ocr_config.Config { + return c.OCR +} + +func (c TestConfig) GetConfigurationName() string { + return c.ConfigurationName +} + +type Common struct { + ChainlinkNodeFunding *float64 `toml:"chainlink_node_funding"` +} + +func (c *Common) Validate() error { + if c.ChainlinkNodeFunding != nil && *c.ChainlinkNodeFunding < 0 { + return fmt.Errorf("chainlink node funding must be positive") + } + + return nil +} + +type Product string + +const ( + Automation Product = "automation" + Cron Product = "cron" + DirectRequest Product = "direct_request" + Flux Product = "flux" + ForwarderOcr Product = "forwarder_ocr" + ForwarderOcr2 Product = "forwarder_ocr2" + Functions Product = "functions" + Keeper Product = "keeper" + LogPoller Product = "log_poller" + Node Product = "node" + OCR Product = "ocr" + OCR2 Product = "ocr2" + OCR2VRF Product = "ocr2vrf" + RunLog Product = "runlog" + VRF Product = "vrf" + VRFv2 Product = "vrfv2" + VRFv2Plus Product = "vrfv2plus" +) + +var TestTypesWithLoki = []string{"Load", "Soak", "Stress", "Spike", "Volume"} + +const TestTypeEnvVarName = "TEST_TYPE" + +func GetConfigurationNameFromEnv() (string, error) { + testType := os.Getenv(TestTypeEnvVarName) + if testType == "" { + return "", fmt.Errorf("%s env var not set", TestTypeEnvVarName) + } + + return cases.Title(language.English, cases.NoLower).String(testType), nil +} + +const ( + Base64OverrideEnvVarName = k8s_config.EnvBase64ConfigOverride + NoKey = "NO_KEY" +) + +func GetConfig(configurationName string, product Product) (TestConfig, error) { + logger := logging.GetTestLogger(nil) + + configurationName = strings.ReplaceAll(configurationName, "/", "_") + configurationName = strings.ReplaceAll(configurationName, " ", "_") + configurationName = cases.Title(language.English, cases.NoLower).String(configurationName) + fileNames := []string{ + "default.toml", + fmt.Sprintf("%s.toml", product), + "overrides.toml", + } + + testConfig := TestConfig{} + testConfig.ConfigurationName = configurationName + logger.Debug().Msgf("Will apply configuration named '%s' if it is found in any of the configs", configurationName) + + var handleSpecialOverrides = func(logger zerolog.Logger, filename, configurationName string, target *TestConfig, content []byte, product Product) error { + switch product { + case Automation: + return handleAutomationConfigOverride(logger, filename, configurationName, target, content) + default: + err := ctf_config.BytesToAnyTomlStruct(logger, filename, configurationName, &testConfig, content) + if err != nil { + return errors.Wrapf(err, "error reading file %s", filename) + } + + return nil + } + } + + // read embedded configs is build tag "embed" is set + // this makes our life much easier when using a binary + if areConfigsEmbedded { + logger.Info().Msg("Reading embedded configs") + embeddedFiles := []string{"default.toml", fmt.Sprintf("%s/%s.toml", product, product)} + for _, fileName := range embeddedFiles { + file, err := embeddedConfigs.ReadFile(fileName) + if err != nil && errors.Is(err, os.ErrNotExist) { + logger.Debug().Msgf("Embedded config file %s not found. Continuing", fileName) + continue + } else if err != nil { + return TestConfig{}, errors.Wrapf(err, "error reading embedded config") + } + + err = handleSpecialOverrides(logger, fileName, configurationName, &testConfig, file, product) + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error unmarshalling embedded config") + } + } + } + + logger.Info().Msg("Reading configs from file system") + for _, fileName := range fileNames { + logger.Debug().Msgf("Looking for config file %s", fileName) + filePath, err := osutil.FindFile(fileName, osutil.DEFAULT_STOP_FILE_NAME, 3) + + if err != nil && errors.Is(err, os.ErrNotExist) { + logger.Debug().Msgf("Config file %s not found", fileName) + continue + } else if err != nil { + return TestConfig{}, errors.Wrapf(err, "error looking for file %s", filePath) + } + logger.Debug().Str("location", filePath).Msgf("Found config file %s", fileName) + + content, err := readFile(filePath) + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error reading file %s", filePath) + } + + err = handleSpecialOverrides(logger, fileName, configurationName, &testConfig, content, product) + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error reading file %s", filePath) + } + } + + logger.Info().Msg("Reading configs from Base64 override env var") + configEncoded, isSet := os.LookupEnv(Base64OverrideEnvVarName) + if isSet && configEncoded != "" { + logger.Debug().Msgf("Found base64 config override environment variable '%s' found", Base64OverrideEnvVarName) + decoded, err := base64.StdEncoding.DecodeString(configEncoded) + if err != nil { + return TestConfig{}, err + } + + err = handleSpecialOverrides(logger, Base64OverrideEnvVarName, configurationName, &testConfig, decoded, product) + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error unmarshaling base64 config") + } + } else { + logger.Debug().Msg("Base64 config override from environment variable not found") + } + + // it neede some custom logic, so we do it separately + err := testConfig.readNetworkConfiguration() + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error reading network config") + } + + logger.Debug().Msg("Validating test config") + err = testConfig.Validate() + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error validating test config") + } + + if testConfig.Common == nil { + testConfig.Common = &Common{} + } + + logger.Debug().Msg("Correct test config constructed successfully") + return testConfig, nil +} + +func (c *TestConfig) readNetworkConfiguration() error { + // currently we need to read that kind of secrets only for network configuration + if c == nil { + c.Network = &ctf_config.NetworkConfig{} + } + + c.Network.UpperCaseNetworkNames() + err := c.Network.Default() + if err != nil { + return errors.Wrapf(err, "error reading default network config") + } + + // this is the only value we need to generate dynamically before starting a new simulated chain + if c.PrivateEthereumNetwork != nil && c.PrivateEthereumNetwork.EthereumChainConfig != nil { + c.PrivateEthereumNetwork.EthereumChainConfig.GenerateGenesisTimestamp() + } + + return nil +} + +func (c *TestConfig) Validate() error { + defer func() { + if r := recover(); r != nil { + panic(fmt.Errorf("Panic during test config validation: '%v'. Most probably due to presence of partial product config", r)) + } + }() + if c.ChainlinkImage == nil { + return fmt.Errorf("chainlink image config must be set") + } + if err := c.ChainlinkImage.Validate(); err != nil { + return errors.Wrapf(err, "chainlink image config validation failed") + } + if c.ChainlinkUpgradeImage != nil { + if err := c.ChainlinkUpgradeImage.Validate(); err != nil { + return errors.Wrapf(err, "chainlink upgrade image config validation failed") + } + } + if err := c.Network.Validate(); err != nil { + return errors.Wrapf(err, "network config validation failed") + } + + if c.Logging == nil { + return fmt.Errorf("logging config must be set") + } + + if err := c.Logging.Validate(); err != nil { + return errors.Wrapf(err, "logging config validation failed") + } + + // require Loki config only if these tests run locally + _, willUseRemoteRunner := os.LookupEnv(k8s_config.EnvVarJobImage) + _, isInsideK8s := os.LookupEnv(k8s_config.EnvVarInsideK8s) + if (!willUseRemoteRunner && !isInsideK8s) && slices.Contains(TestTypesWithLoki, c.ConfigurationName) { + if c.Logging.Loki == nil { + return fmt.Errorf("for local execution you must set Loki config in logging config") + } + + if err := c.Logging.Loki.Validate(); err != nil { + return errors.Wrapf(err, "loki config validation failed") + } + } + + if c.Logging.LogStream != nil && slices.Contains(c.Logging.LogStream.LogTargets, "loki") { + if c.Logging.Loki == nil { + return fmt.Errorf("in order to use Loki as logging target you must set Loki config in logging config") + } + + if err := c.Logging.Loki.Validate(); err != nil { + return errors.Wrapf(err, "loki config validation failed") + } + } + + if c.Pyroscope != nil { + if err := c.Pyroscope.Validate(); err != nil { + return errors.Wrapf(err, "pyroscope config validation failed") + } + } + + if c.PrivateEthereumNetwork != nil { + if err := c.PrivateEthereumNetwork.Validate(); err != nil { + return errors.Wrapf(err, "private ethereum network config validation failed") + } + } + + if c.Common != nil { + if err := c.Common.Validate(); err != nil { + return errors.Wrapf(err, "Common config validation failed") + } + } + + if c.Automation != nil { + if err := c.Automation.Validate(); err != nil { + return errors.Wrapf(err, "Automation config validation failed") + } + } + + if c.Functions != nil { + if err := c.Functions.Validate(); err != nil { + return errors.Wrapf(err, "Functions config validation failed") + } + } + + if c.Keeper != nil { + if err := c.Keeper.Validate(); err != nil { + return errors.Wrapf(err, "Keeper config validation failed") + } + } + + if c.LogPoller != nil { + if err := c.LogPoller.Validate(); err != nil { + return errors.Wrapf(err, "LogPoller config validation failed") + } + } + + if c.OCR != nil { + if err := c.OCR.Validate(); err != nil { + return errors.Wrapf(err, "OCR config validation failed") + } + } + + if c.VRF != nil { + if err := c.VRF.Validate(); err != nil { + return errors.Wrapf(err, "VRF config validation failed") + } + } + + if c.VRFv2 != nil { + if err := c.VRFv2.Validate(); err != nil { + return errors.Wrapf(err, "VRFv2 config validation failed") + } + } + + if c.VRFv2Plus != nil { + if err := c.VRFv2Plus.Validate(); err != nil { + return errors.Wrapf(err, "VRFv2Plus config validation failed") + } + } + + return nil +} + +func readFile(filePath string) ([]byte, error) { + content, err := os.ReadFile(filePath) + if err != nil { + return nil, errors.Wrapf(err, "error reading file %s", filePath) + } + + return content, nil +} + +func handleAutomationConfigOverride(logger zerolog.Logger, filename, configurationName string, target *TestConfig, content []byte) error { + logger.Debug().Msgf("Handling automation config override for %s", filename) + oldConfig := MustCopy(target) + newConfig := TestConfig{} + + err := ctf_config.BytesToAnyTomlStruct(logger, filename, configurationName, &target, content) + if err != nil { + return errors.Wrapf(err, "error reading file %s", filename) + } + + err = ctf_config.BytesToAnyTomlStruct(logger, filename, configurationName, &newConfig, content) + if err != nil { + return errors.Wrapf(err, "error reading file %s", filename) + } + + // override instead of merging + if (newConfig.Automation != nil && len(newConfig.Automation.Load) > 0) && (oldConfig != nil && oldConfig.Automation != nil && len(oldConfig.Automation.Load) > 0) { + target.Automation.Load = newConfig.Automation.Load + } + + return nil +} diff --git a/integration-tests/testconfig/testconfig_test.go b/integration-tests/testconfig/testconfig_test.go new file mode 100644 index 00000000000..4a9dbdaade3 --- /dev/null +++ b/integration-tests/testconfig/testconfig_test.go @@ -0,0 +1,88 @@ +package testconfig + +import ( + "encoding/base64" + "math/big" + "os" + "testing" + + "github.com/pelletier/go-toml/v2" + "github.com/test-go/testify/require" + + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + a_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" +) + +func TestBase64ConfigRead(t *testing.T) { + networkConfigTOML := ` + [RpcHttpUrls] + arbitrum_goerli = ["https://devnet-1.mt/ABC/rpc/"] + optimism_goerli = ["https://devnet-3.mt/ABC/rpc/"] + + [RpcWsUrls] + arbitrum_goerli = ["wss://devnet-1.mt/ABC/rpc/"] + optimism_goerli = ["wss://devnet-2.mt/ABC/rpc/"] + ` + networksEncoded := base64.StdEncoding.EncodeToString([]byte(networkConfigTOML)) + os.Setenv(ctf_config.Base64NetworkConfigEnvVarName, networksEncoded) + + testConfig := TestConfig{ + Automation: &a_config.Config{ + General: &a_config.General{ + NumberOfNodes: ptr.Ptr(7), + Duration: ptr.Ptr(9), + BlockTime: ptr.Ptr(10), + SpecType: ptr.Ptr("minimum"), + ChainlinkNodeLogLevel: ptr.Ptr("debug"), + }, + Load: []a_config.Load{ + { + NumberOfUpkeeps: ptr.Ptr(1), + NumberOfEvents: ptr.Ptr(2), + NumberOfSpamMatchingEvents: ptr.Ptr(3), + NumberOfSpamNonMatchingEvents: ptr.Ptr(4), + CheckBurnAmount: big.NewInt(5), + PerformBurnAmount: big.NewInt(6), + SharedTrigger: ptr.Ptr(true), + }, + { + NumberOfUpkeeps: ptr.Ptr(3), + NumberOfEvents: ptr.Ptr(2), + NumberOfSpamMatchingEvents: ptr.Ptr(3), + NumberOfSpamNonMatchingEvents: ptr.Ptr(7), + CheckBurnAmount: big.NewInt(5), + PerformBurnAmount: big.NewInt(6), + SharedTrigger: ptr.Ptr(false), + }, + }, + }, + Network: &ctf_config.NetworkConfig{ + SelectedNetworks: []string{"OPTIMISM_GOERLI"}, + RpcHttpUrls: map[string][]string{ + "OPTIMISM_GOERLI": {"http://localhost:8545"}, + }, + WalletKeys: map[string][]string{ + "OPTIMISM_GOERLI": {"0x3333333333333333333333333333333333333333"}, + }, + }, + } + + configMarshalled, err := toml.Marshal(testConfig) + require.NoError(t, err, "Error marshalling test config") + + testConfigEncoded := base64.StdEncoding.EncodeToString(configMarshalled) + os.Setenv(Base64OverrideEnvVarName, testConfigEncoded) + + readConfig, err := GetConfig("test", Automation) + require.NoError(t, err, "Error reading config") + + require.NotNil(t, readConfig.Automation, "Automation config read from base64 is nil") + require.Equal(t, testConfig.Automation.General, readConfig.Automation.General, "General automation config does not match expected") + require.EqualValues(t, testConfig.Automation.Load, readConfig.Automation.Load, "Load automation config does not match expected") + require.NotNil(t, readConfig.Network, "Network config read from base64 is nil") + require.Equal(t, testConfig.Network.SelectedNetworks, readConfig.Network.SelectedNetworks, "SelectedNetwork config entry read from base64 does not match expected") + require.Equal(t, []string{"http://localhost:8545"}, readConfig.Network.RpcHttpUrls["OPTIMISM_GOERLI"], "RpcHttpUrls config entry read from base64 does not match expected") + require.Equal(t, []string{"wss://devnet-2.mt/ABC/rpc/"}, readConfig.Network.RpcWsUrls["OPTIMISM_GOERLI"], "RpcWsUrls config entry read from base64 network defaults does not match expected") + require.Equal(t, testConfig.Network.WalletKeys, readConfig.Network.WalletKeys, "WalletKeys config entry read from base64 does not match expected") +} diff --git a/integration-tests/testconfig/vrf/config.go b/integration-tests/testconfig/vrf/config.go new file mode 100644 index 00000000000..d009f5bf667 --- /dev/null +++ b/integration-tests/testconfig/vrf/config.go @@ -0,0 +1,8 @@ +package vrf + +type Config struct { +} + +func (o *Config) Validate() error { + return nil +} diff --git a/integration-tests/testconfig/vrfv2/config.go b/integration-tests/testconfig/vrfv2/config.go new file mode 100644 index 00000000000..f539d91799c --- /dev/null +++ b/integration-tests/testconfig/vrfv2/config.go @@ -0,0 +1,330 @@ +package testconfig + +import ( + "errors" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" +) + +const ( + ErrDeviationShouldBeLessThanOriginal = "`RandomnessRequestCountPerRequestDeviation` should be less than `RandomnessRequestCountPerRequest`" +) + +type Config struct { + Common *Common `toml:"Common"` + General *General `toml:"General"` + ExistingEnvConfig *ExistingEnvConfig `toml:"ExistingEnv"` + NewEnvConfig *NewEnvConfig `toml:"NewEnv"` + Performance *PerformanceConfig `toml:"Performance"` +} + +func (c *Config) Validate() error { + if c.Common != nil { + if err := c.Common.Validate(); err != nil { + return err + } + } + if c.General != nil { + if err := c.General.Validate(); err != nil { + return err + } + } + if c.Performance != nil { + if err := c.Performance.Validate(); err != nil { + return err + } + if *c.Performance.UseExistingEnv { + if c.ExistingEnvConfig != nil { + if err := c.ExistingEnvConfig.Validate(); err != nil { + return err + } + } + } else { + if c.NewEnvConfig != nil { + if err := c.NewEnvConfig.Validate(); err != nil { + return err + } + } + } + } + + return nil +} + +type Common struct { + CancelSubsAfterTestRun *bool `toml:"cancel_subs_after_test_run"` +} + +func (c *Common) Validate() error { + return nil +} + +type PerformanceConfig struct { + TestDuration *blockchain.StrDuration `toml:"test_duration"` + RPS *int64 `toml:"rps"` + RateLimitUnitDuration *blockchain.StrDuration `toml:"rate_limit_unit_duration"` + + // Using existing environment and contracts + UseExistingEnv *bool `toml:"use_existing_env"` + CoordinatorAddress *string + ConsumerAddress *string + LinkAddress *string + SubID *uint64 + KeyHash *string +} + +func (c *PerformanceConfig) Validate() error { + if c.TestDuration == nil || c.TestDuration.Duration == 0 { + return errors.New("test_duration must be set to a positive value") + } + if c.RPS == nil || *c.RPS == 0 { + return errors.New("rps must be set to a positive value") + } + if c.RateLimitUnitDuration == nil { + return errors.New("rate_limit_unit_duration must be set ") + } + if c.UseExistingEnv == nil { + return errors.New("use_existing_env must be set ") + } + + return nil +} + +type ExistingEnvConfig struct { + CoordinatorAddress *string `toml:"coordinator_address"` + ConsumerAddress *string `toml:"consumer_address"` + LinkAddress *string `toml:"link_address"` + SubID *uint64 `toml:"sub_id"` + KeyHash *string `toml:"key_hash"` + CreateFundSubsAndAddConsumers *bool `toml:"create_fund_subs_and_add_consumers"` + NodeSendingKeys []string `toml:"node_sending_keys"` + Funding +} + +func (c *ExistingEnvConfig) Validate() error { + if c.CreateFundSubsAndAddConsumers == nil { + return errors.New("create_fund_subs_and_add_consumers must be set ") + } + if c.CoordinatorAddress == nil { + return errors.New("coordinator_address must be set when using existing environment") + } + if !common.IsHexAddress(*c.CoordinatorAddress) { + return errors.New("coordinator_address must be a valid hex address") + } + if c.KeyHash == nil { + return errors.New("key_hash must be set when using existing environment") + } + if *c.KeyHash == "" { + return errors.New("key_hash must be a non-empty string") + } + if c.LinkAddress != nil && !common.IsHexAddress(*c.LinkAddress) { + return errors.New("link_address must be a valid hex address") + } + + if *c.CreateFundSubsAndAddConsumers { + if err := c.Funding.Validate(); err != nil { + return err + } + if err := c.Funding.SubFunding.Validate(); err != nil { + return err + } + } else { + if c.ConsumerAddress == nil || *c.ConsumerAddress == "" { + return errors.New("consumer_address must be set when using existing environment") + } + if !common.IsHexAddress(*c.ConsumerAddress) { + return errors.New("consumer_address must be a valid hex address") + } + if c.SubID == nil { + return errors.New("sub_id must be set when using existing environment") + } + if *c.SubID == 0 { + return errors.New("sub_id must be a positive value") + } + } + + if c.NodeSendingKeys != nil { + for _, key := range c.NodeSendingKeys { + if !common.IsHexAddress(key) { + return errors.New("node_sending_keys must be a valid hex address") + } + } + } + + return nil +} + +type NewEnvConfig struct { + *Funding +} + +func (c *NewEnvConfig) Validate() error { + if c.Funding != nil { + return c.Funding.Validate() + } + + return nil +} + +type Funding struct { + SubFunding + NodeSendingKeyFunding *float64 `toml:"node_sending_key_funding"` + NodeSendingKeyFundingMin *float64 `toml:"node_sending_key_funding_min"` +} + +func (c *Funding) Validate() error { + if c.NodeSendingKeyFunding != nil && *c.NodeSendingKeyFunding <= 0 { + return errors.New("when set node_sending_key_funding must be a positive value") + } + if c.NodeSendingKeyFundingMin != nil && *c.NodeSendingKeyFundingMin <= 0 { + return errors.New("when set node_sending_key_funding_min must be a positive value") + } + + return nil +} + +type SubFunding struct { + SubFundsLink *float64 `toml:"sub_funds_link"` +} + +func (c *SubFunding) Validate() error { + if c.SubFundsLink != nil && *c.SubFundsLink < 0 { + return errors.New("when set sub_funds_link must be a non-negative value") + } + + return nil +} + +type General struct { + CLNodeMaxGasPriceGWei *int64 `toml:"max_gas_price_gwei"` // Max gas price in GWei for the chainlink node + LinkNativeFeedResponse *int64 `toml:"link_native_feed_response"` // Response of the LINK/ETH feed + MinimumConfirmations *uint16 `toml:"minimum_confirmations" ` // Minimum number of confirmations for the VRF Coordinator + SubscriptionFundingAmountLink *float64 `toml:"subscription_funding_amount_link"` // Amount of LINK to fund the subscription with + NumberOfWords *uint32 `toml:"number_of_words" ` // Number of words to request + CallbackGasLimit *uint32 `toml:"callback_gas_limit" ` // Gas limit for the callback + MaxGasLimitCoordinatorConfig *uint32 `toml:"max_gas_limit_coordinator_config"` // Max gas limit for the VRF Coordinator config + FallbackWeiPerUnitLink *int64 `toml:"fallback_wei_per_unit_link"` // Fallback wei per unit LINK for the VRF Coordinator config + StalenessSeconds *uint32 `toml:"staleness_seconds" ` // Staleness in seconds for the VRF Coordinator config + GasAfterPaymentCalculation *uint32 `toml:"gas_after_payment_calculation" ` // Gas after payment calculation for the VRF Coordinator + FulfillmentFlatFeeLinkPPMTier1 *uint32 `toml:"fulfilment_flat_fee_link_ppm_tier_1"` + FulfillmentFlatFeeLinkPPMTier2 *uint32 `toml:"fulfilment_flat_fee_link_ppm_tier_2"` + FulfillmentFlatFeeLinkPPMTier3 *uint32 `toml:"fulfilment_flat_fee_link_ppm_tier_3"` + FulfillmentFlatFeeLinkPPMTier4 *uint32 `toml:"fulfilment_flat_fee_link_ppm_tier_4"` + FulfillmentFlatFeeLinkPPMTier5 *uint32 `toml:"fulfilment_flat_fee_link_ppm_tier_5"` + ReqsForTier2 *int64 `toml:"reqs_for_tier_2"` + ReqsForTier3 *int64 `toml:"reqs_for_tier_3"` + ReqsForTier4 *int64 `toml:"reqs_for_tier_4"` + ReqsForTier5 *int64 `toml:"reqs_for_tier_5"` + + NumberOfSubToCreate *int `toml:"number_of_sub_to_create"` // Number of subscriptions to create + + RandomnessRequestCountPerRequest *uint16 `toml:"randomness_request_count_per_request"` // How many randomness requests to send per request + RandomnessRequestCountPerRequestDeviation *uint16 `toml:"randomness_request_count_per_request_deviation"` // How many randomness requests to send per request + + RandomWordsFulfilledEventTimeout *blockchain.StrDuration `toml:"random_words_fulfilled_event_timeout"` // How long to wait for the RandomWordsFulfilled event to be emitted + + // Wrapper Config + WrapperGasOverhead *uint32 `toml:"wrapped_gas_overhead"` + CoordinatorGasOverhead *uint32 `toml:"coordinator_gas_overhead"` + WrapperPremiumPercentage *uint8 `toml:"wrapper_premium_percentage"` + WrapperMaxNumberOfWords *uint8 `toml:"wrapper_max_number_of_words"` + WrapperConsumerFundingAmountNativeToken *float64 `toml:"wrapper_consumer_funding_amount_native_token"` + WrapperConsumerFundingAmountLink *int64 `toml:"wrapper_consumer_funding_amount_link"` +} + +func (c *General) Validate() error { + if c.CLNodeMaxGasPriceGWei == nil || *c.CLNodeMaxGasPriceGWei == 0 { + return errors.New("max_gas_price_gwei must be set to a positive value") + } + if c.LinkNativeFeedResponse == nil || *c.LinkNativeFeedResponse == 0 { + return errors.New("link_native_feed_response must be set to a positive value") + } + if c.MinimumConfirmations == nil { + return errors.New("minimum_confirmations must be set to a non-negative value") + } + if c.SubscriptionFundingAmountLink == nil || *c.SubscriptionFundingAmountLink == 0 { + return errors.New("subscription_funding_amount_link must be set to a positive value") + } + if c.NumberOfWords == nil || *c.NumberOfWords == 0 { + return errors.New("number_of_words must be set to a positive value") + } + if c.CallbackGasLimit == nil || *c.CallbackGasLimit == 0 { + return errors.New("callback_gas_limit must be set to a positive value") + } + if c.MaxGasLimitCoordinatorConfig == nil || *c.MaxGasLimitCoordinatorConfig == 0 { + return errors.New("max_gas_limit_coordinator_config must be set to a positive value") + } + if c.FallbackWeiPerUnitLink == nil || *c.FallbackWeiPerUnitLink == 0 { + return errors.New("fallback_wei_per_unit_link must be set to a positive value") + } + if c.StalenessSeconds == nil || *c.StalenessSeconds == 0 { + return errors.New("staleness_seconds must be set to a positive value") + } + if c.GasAfterPaymentCalculation == nil || *c.GasAfterPaymentCalculation == 0 { + return errors.New("gas_after_payment_calculation must be set to a positive value") + } + if c.FulfillmentFlatFeeLinkPPMTier1 == nil || *c.FulfillmentFlatFeeLinkPPMTier1 == 0 { + return errors.New("fulfilment_flat_fee_link_ppm_tier_1 must be set to a positive value") + } + if c.FulfillmentFlatFeeLinkPPMTier2 == nil || *c.FulfillmentFlatFeeLinkPPMTier2 == 0 { + return errors.New("fulfilment_flat_fee_link_ppm_tier_2 must be set to a positive value") + } + if c.FulfillmentFlatFeeLinkPPMTier3 == nil || *c.FulfillmentFlatFeeLinkPPMTier3 == 0 { + return errors.New("fulfilment_flat_fee_link_ppm_tier_3 must be set to a positive value") + } + if c.FulfillmentFlatFeeLinkPPMTier4 == nil || *c.FulfillmentFlatFeeLinkPPMTier4 == 0 { + return errors.New("fulfilment_flat_fee_link_ppm_tier_4 must be set to a positive value") + } + if c.FulfillmentFlatFeeLinkPPMTier5 == nil || *c.FulfillmentFlatFeeLinkPPMTier5 == 0 { + return errors.New("fulfilment_flat_fee_link_ppm_tier_5 must be set to a positive value") + } + if c.ReqsForTier2 == nil || *c.ReqsForTier2 < 0 { + return errors.New("reqs_for_tier_2 must be set to a non-negative value") + } + if c.ReqsForTier3 == nil || *c.ReqsForTier3 < 0 { + return errors.New("reqs_for_tier_3 must be set to a non-negative value") + } + if c.ReqsForTier4 == nil || *c.ReqsForTier4 < 0 { + return errors.New("reqs_for_tier_4 must be set to a non-negative value") + } + if c.ReqsForTier5 == nil || *c.ReqsForTier5 < 0 { + return errors.New("reqs_for_tier_5 must be set to a non-negative value") + } + if c.NumberOfSubToCreate == nil || *c.NumberOfSubToCreate == 0 { + return errors.New("number_of_sub_to_create must be set to a positive value") + } + if c.RandomnessRequestCountPerRequest == nil || *c.RandomnessRequestCountPerRequest == 0 { + return errors.New("randomness_request_count_per_request must be set to a positive value") + } + if c.RandomnessRequestCountPerRequestDeviation == nil { + return errors.New("randomness_request_count_per_request_deviation must be set to a non-negative value") + } + if c.RandomWordsFulfilledEventTimeout == nil || c.RandomWordsFulfilledEventTimeout.Duration == 0 { + return errors.New("random_words_fulfilled_event_timeout must be set to a positive value") + } + if c.WrapperGasOverhead == nil { + return errors.New("wrapped_gas_overhead must be set to a non-negative value") + } + if c.CoordinatorGasOverhead == nil || *c.CoordinatorGasOverhead == 0 { + return errors.New("coordinator_gas_overhead must be set to a non-negative value") + } + if c.WrapperPremiumPercentage == nil || *c.WrapperPremiumPercentage == 0 { + return errors.New("wrapper_premium_percentage must be set to a positive value") + } + if c.WrapperMaxNumberOfWords == nil || *c.WrapperMaxNumberOfWords == 0 { + return errors.New("wrapper_max_number_of_words must be set to a positive value") + } + if c.WrapperConsumerFundingAmountNativeToken == nil || *c.WrapperConsumerFundingAmountNativeToken < 0 { + return errors.New("wrapper_consumer_funding_amount_native_token must be set to a non-negative value") + } + if c.WrapperConsumerFundingAmountLink == nil || *c.WrapperConsumerFundingAmountLink < 0 { + return errors.New("wrapper_consumer_funding_amount_link must be set to a non-negative value") + } + if *c.RandomnessRequestCountPerRequest <= *c.RandomnessRequestCountPerRequestDeviation { + return errors.New(ErrDeviationShouldBeLessThanOriginal) + } + + return nil +} diff --git a/integration-tests/testconfig/vrfv2/example.toml b/integration-tests/testconfig/vrfv2/example.toml new file mode 100644 index 00000000000..bc826ebe05e --- /dev/null +++ b/integration-tests/testconfig/vrfv2/example.toml @@ -0,0 +1,136 @@ +# Example of full config with all fields +# General part +[ChainlinkImage] +image="public.ecr.aws/chainlink/chainlink" +version="2.7.0" + +[Logging] +# if set to true will save logs even if test did not fail +test_log_collect=false + +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth="loki-basic-auth" +# only needed for cloud grafana +bearer_token="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +bearer_token="my-awesome-token" + +# if you want to use polygon_mumbial +[Network] +selected_networks=["polygon_mumbai"] + +[Network.RpcHttpUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.RpcWsUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.WalletKeys] +polygon_mumbai = ["change-me-to-your-PK"] + +[PrivateEthereumNetwork] +# pos or pow +consensus_type="pos" +# only prysm supported currently +consensus_layer="prysm" +# geth, besu, nethermind or erigon +execution_layer="geth" +# if true after env started it will wait for at least 1 epoch to be finalised before continuing +wait_for_finalization=false + +[PrivateEthereumNetwork.EthereumChainConfig] +# duration of single slot, lower => faster block production, must be >= 4 +seconds_per_slot=12 +# numer of slots in epoch, lower => faster epoch finalisation, must be >= 4 +slots_per_epoch=6 +# extra genesis gelay, no need to modify, but it should be after all validators/beacon chain starts +genesis_delay=15 +# number of validators in the network +validator_count=8 +chain_id=1337 +# list of addresses to be prefunded in genesis +addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] + +# Common +[Common] +chainlink_node_funding = 0.5 + +# Product part +[VRFv2] +[VRFv2.Common] +cancel_subs_after_test_run = true + +[VRFv2.General] +max_gas_price_gwei = 1000 +link_native_feed_response = 1000000000000000000 +minimum_confirmations = 3 +subscription_funding_amount_link = 5.0 +number_of_words = 3 +callback_gas_limit = 1000000 +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = 60000000000000000 +staleness_seconds = 86400 +gas_after_payment_calculation = 33825 +fulfilment_flat_fee_link_ppm_tier_1 = 500 +fulfilment_flat_fee_link_ppm_tier_2 = 500 +fulfilment_flat_fee_link_ppm_tier_3 = 500 +fulfilment_flat_fee_link_ppm_tier_4 = 500 +fulfilment_flat_fee_link_ppm_tier_5 = 500 +reqs_for_tier_2 = 0 +reqs_for_tier_3 = 0 +reqs_for_tier_4 = 0 +reqs_for_tier_5 = 0 +number_of_sub_to_create = 1 +randomness_request_count_per_request = 1 +randomness_request_count_per_request_deviation = 0 +random_words_fulfilled_event_timeout = "2m" +wrapped_gas_overhead = 50000 +coordinator_gas_overhead = 52000 +wrapper_premium_percentage = 25 +wrapper_max_number_of_words = 10 +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 10 + +[VRFv2.Performance] +rate_limit_unit_duration = "3s" +rps = 1 + +[VRFv2.NewEnv] +sub_funds_link = 1000 +node_sending_key_funding = 1000 + +[VRFv2.ExistingEnv] +coordinator_address = "" +consumer_address = "" +sub_id = 1 +key_hash = "" +create_fund_subs_and_add_consumers = true +link_address = "" +sub_funds_link = 10 +node_sending_key_funding_min = 1 +node_sending_keys = [ + "", + "", + "", + "", + "", + "", +] \ No newline at end of file diff --git a/integration-tests/testconfig/vrfv2/vrfv2.toml b/integration-tests/testconfig/vrfv2/vrfv2.toml new file mode 100644 index 00000000000..64e628c4afa --- /dev/null +++ b/integration-tests/testconfig/vrfv2/vrfv2.toml @@ -0,0 +1,143 @@ +# default config +[Common] +chainlink_node_funding = 0.1 + +[VRFv2] +[VRFv2.General] +max_gas_price_gwei = 10 +link_native_feed_response = 1000000000000000000 +minimum_confirmations = 3 +subscription_funding_amount_link = 5.0 +number_of_words = 3 +callback_gas_limit = 1000000 +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = 60000000000000000 +staleness_seconds = 86400 +gas_after_payment_calculation = 33825 +fulfilment_flat_fee_link_ppm_tier_1 = 500 +fulfilment_flat_fee_link_ppm_tier_2 = 500 +fulfilment_flat_fee_link_ppm_tier_3 = 500 +fulfilment_flat_fee_link_ppm_tier_4 = 500 +fulfilment_flat_fee_link_ppm_tier_5 = 500 +reqs_for_tier_2 = 0 +reqs_for_tier_3 = 0 +reqs_for_tier_4 = 0 +reqs_for_tier_5 = 0 +number_of_sub_to_create = 1 +randomness_request_count_per_request = 1 +randomness_request_count_per_request_deviation = 0 +random_words_fulfilled_event_timeout = "2m" +wrapped_gas_overhead = 50000 +coordinator_gas_overhead = 52000 +wrapper_premium_percentage = 25 +wrapper_max_number_of_words = 10 +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 10 + +# load test specific config +[Load.VRFv2] +[Load.VRFv2.Common] +cancel_subs_after_test_run = true + +[Load.VRFv2.General] +minimum_confirmations = 3 +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 + +[Load.VRFv2.Performance] +# approx 60 RPM - 1 tx request with 3 rand requests in each tx every 3 seconds +rate_limit_unit_duration = "3s" +rps = 1 + +[Load.VRFv2.NewEnv] +sub_funds_link = 1000 +node_sending_key_funding = 1000 + +[Load.VRFv2.ExistingEnv] +sub_id = 1 +create_fund_subs_and_add_consumers = true +sub_funds_link = 10 +node_sending_key_funding_min = 1 +node_sending_keys = [] + +# soak test specific config +[Soak.VRFv2] +[VRFv2.Common] +cancel_subs_after_test_run = true + +[Soak.VRFv2.General] +minimum_confirmations = 3 +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 + +[Soak.VRFv2.Performance] +# 10 RPM - 1 tx request with 1 rand request in each tx every 6 seconds +rate_limit_unit_duration = "6s" +rps = 1 + +[Soak.VRFv2.NewEnv] +sub_funds_link = 1000 +node_sending_key_funding = 1000 + +[Soak.VRFv2.ExistingEnv] +sub_id = 1 +create_fund_subs_and_add_consumers = true +sub_funds_link = 10 +node_sending_key_funding_min = 1 +node_sending_keys = [] + +# spike test specific config +[Spike.VRFv2] +[Spike.VRFv2.Common] +cancel_subs_after_test_run = true + +[Spike.VRFv2.General] +minimum_confirmations = 3 +randomness_request_count_per_request = 150 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 + +[Spike.VRFv2.Performance] +# approx 150 RPM - 1 tx request with 150 rand requests in each tx every 60 seconds +rate_limit_unit_duration = "1m" +rps = 1 + +[Spike.VRFv2.NewEnv] +sub_funds_link = 1000 +node_sending_key_funding = 1000 + +[Spike.VRFv2.ExistingEnv] +sub_id = 1 +create_fund_subs_and_add_consumers = true +sub_funds_link = 10 +node_sending_key_funding_min = 1 +node_sending_keys = [] + +# stress test specific config +[Stress.VRFv2] +[Stress.VRFv2.Common] +cancel_subs_after_test_run = true + +[Stress.VRFv2.General] +minimum_confirmations = 3 +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 + +[Stress.VRFv2.Performance] +# approx 540 RPM - 3 tx requests per second with 4 rand requests in each tx +rate_limit_unit_duration = "1s" +rps = 3 + +[Stress.VRFv2.NewEnv] +sub_funds_link = 1000 +node_sending_key_funding = 1000 + +[Stress.VRFv2.ExistingEnv] +sub_id = 1 +create_fund_subs_and_add_consumers = true +sub_funds_link = 10 +node_sending_key_funding_min = 1 +node_sending_keys = [] diff --git a/integration-tests/testconfig/vrfv2plus/config.go b/integration-tests/testconfig/vrfv2plus/config.go new file mode 100644 index 00000000000..667803e06b6 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/config.go @@ -0,0 +1,158 @@ +package testconfig + +import ( + "errors" + + vrfv2 "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2" +) + +type BillingType string + +const ( + BillingType_Link BillingType = "LINK" + BillingType_Native BillingType = "NATIVE" + BillingType_Link_and_Native BillingType = "LINK_AND_NATIVE" +) + +type Config struct { + Common *Common `toml:"Common"` + General *General `toml:"General"` + ExistingEnvConfig *ExistingEnvConfig `toml:"ExistingEnv"` + NewEnvConfig *NewEnvConfig `toml:"NewEnv"` + Performance *vrfv2.PerformanceConfig `toml:"Performance"` +} + +func (c *Config) Validate() error { + if c.Common != nil { + if err := c.Common.Validate(); err != nil { + return err + } + } + if c.General != nil { + if err := c.General.Validate(); err != nil { + return err + } + } + if c.Performance != nil { + if err := c.Performance.Validate(); err != nil { + return err + } + if *c.Performance.UseExistingEnv { + if c.ExistingEnvConfig != nil { + if err := c.ExistingEnvConfig.Validate(); err != nil { + return err + } + } + } else { + if c.NewEnvConfig != nil { + if err := c.NewEnvConfig.Validate(); err != nil { + return err + } + } + } + } + + return nil +} + +type Common struct { + *vrfv2.Common +} + +func (c *Common) Validate() error { + if c.Common == nil { + return nil + } + return c.Common.Validate() +} + +type General struct { + *vrfv2.General + SubscriptionBillingType *string `toml:"subscription_billing_type"` // Billing type for the subscription + SubscriptionFundingAmountNative *float64 `toml:"subscription_funding_amount_native"` // Amount of LINK to fund the subscription with + FulfillmentFlatFeeLinkPPM *uint32 `toml:"fulfillment_flat_fee_link_ppm"` // Flat fee in ppm for LINK for the VRF Coordinator config + FulfillmentFlatFeeNativePPM *uint32 `toml:"fulfillment_flat_fee_native_ppm"` // Flat fee in ppm for native currency for the VRF Coordinator config +} + +func (c *General) Validate() error { + if err := c.General.Validate(); err != nil { + return err + } + if c.SubscriptionBillingType == nil || *c.SubscriptionBillingType == "" { + return errors.New("subscription_billing_type must be set to either: LINK, NATIVE, LINK_AND_NATIVE") + } + if c.SubscriptionFundingAmountNative == nil || *c.SubscriptionFundingAmountNative <= 0 { + return errors.New("subscription_funding_amount_native must be greater than 0") + } + if c.FulfillmentFlatFeeLinkPPM == nil || *c.FulfillmentFlatFeeLinkPPM <= 0 { + return errors.New("fulfillment_flat_fee_link_ppm must be greater than 0") + } + if c.FulfillmentFlatFeeNativePPM == nil || *c.FulfillmentFlatFeeNativePPM <= 0 { + return errors.New("fulfillment_flat_fee_native_ppm must be greater than 0") + } + + return nil +} + +type NewEnvConfig struct { + *Funding +} + +func (c *NewEnvConfig) Validate() error { + if c.Funding == nil { + return nil + } + + return c.Funding.Validate() +} + +type ExistingEnvConfig struct { + *vrfv2.ExistingEnvConfig + Funding +} + +func (c *ExistingEnvConfig) Validate() error { + if c.ExistingEnvConfig != nil { + if err := c.ExistingEnvConfig.Validate(); err != nil { + return err + } + } + + return c.Funding.Validate() +} + +type Funding struct { + SubFunding + NodeSendingKeyFunding *float64 `toml:"node_sending_key_funding"` + NodeSendingKeyFundingMin *float64 `toml:"node_sending_key_funding_min"` +} + +func (c *Funding) Validate() error { + if c.NodeSendingKeyFunding != nil && *c.NodeSendingKeyFunding <= 0 { + return errors.New("when set node_sending_key_funding must be a positive value") + } + if c.NodeSendingKeyFundingMin != nil && *c.NodeSendingKeyFundingMin <= 0 { + return errors.New("when set node_sending_key_funding_min must be a positive value") + } + + return c.SubFunding.Validate() +} + +type SubFunding struct { + SubFundsLink *float64 `toml:"sub_funds_link"` + SubFundsNative *float64 `toml:"sub_funds_native"` +} + +func (c *SubFunding) Validate() error { + if c.SubFundsLink == nil || c.SubFundsNative == nil { + return errors.New("both sub_funds_link and sub_funds_native must be set") + } + if c.SubFundsLink != nil && *c.SubFundsLink < 0 { + return errors.New("sub_funds_link must be a non-negative number") + } + if c.SubFundsNative != nil && *c.SubFundsNative < 0 { + return errors.New("sub_funds_native must be a non-negative number") + } + + return nil +} diff --git a/integration-tests/testconfig/vrfv2plus/example.toml b/integration-tests/testconfig/vrfv2plus/example.toml new file mode 100644 index 00000000000..a9ce5b2dcf5 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/example.toml @@ -0,0 +1,144 @@ +# Example of full config with all fields +# General part +[ChainlinkImage] +image="public.ecr.aws/chainlink/chainlink" +version="2.7.0" + +[Logging] +# if set to true will save logs even if test did not fail +test_log_collect=false + +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth="loki-basic-auth" +# only needed for cloud grafana +bearer_token="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +bearer_token="my-awesome-token" + +# if you want to use polygon_mumbial +[Network] +selected_networks=["polygon_mumbai"] + +[Network.RpcHttpUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.RpcWsUrls] +polygon_mumbai = ["https://my-rpc-endpoint.io"] + +[Network.WalletKeys] +polygon_mumbai = ["change-me-to-your-PK"] + +[PrivateEthereumNetwork] +# pos or pow +consensus_type="pos" +# only prysm supported currently +consensus_layer="prysm" +# geth, besu, nethermind or erigon +execution_layer="geth" +# if true after env started it will wait for at least 1 epoch to be finalised before continuing +wait_for_finalization=false + +[PrivateEthereumNetwork.EthereumChainConfig] +# duration of single slot, lower => faster block production, must be >= 4 +seconds_per_slot=12 +# numer of slots in epoch, lower => faster epoch finalisation, must be >= 4 +slots_per_epoch=6 +# extra genesis gelay, no need to modify, but it should be after all validators/beacon chain starts +genesis_delay=15 +# number of validators in the network +validator_count=8 +chain_id=1337 +# list of addresses to be prefunded in genesis +addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] + +# Common +[Common] +chainlink_node_funding = 0.5 + +# Product part +[VRFv2Plus] +[VRFv2Plus.Common] +cancel_subs_after_test_run = true + +[VRFv2Plus.General] +max_gas_price_gwei = 1000 +link_native_feed_response = 1000000000000000000 +minimum_confirmations = 3 +subscription_billing_type = "LINK_AND_NATIVE" +subscription_funding_amount_link = 5.0 +number_of_words = 3 +callback_gas_limit = 1000000 +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = 60000000000000000 +staleness_seconds = 86400 +gas_after_payment_calculation = 33825 +fulfilment_flat_fee_link_ppm_tier_1 = 500 +fulfilment_flat_fee_link_ppm_tier_2 = 500 +fulfilment_flat_fee_link_ppm_tier_3 = 500 +fulfilment_flat_fee_link_ppm_tier_4 = 500 +fulfilment_flat_fee_link_ppm_tier_5 = 500 +reqs_for_tier_2 = 0 +reqs_for_tier_3 = 0 +reqs_for_tier_4 = 0 +reqs_for_tier_5 = 0 +number_of_sub_to_create = 1 +randomness_request_count_per_request = 1 +randomness_request_count_per_request_deviation = 0 +random_words_fulfilled_event_timeout = "2m" +wrapped_gas_overhead = 50000 +coordinator_gas_overhead = 52000 +wrapper_premium_percentage = 25 +wrapper_max_number_of_words = 10 +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 10 +subscription_funding_amount_native=1 +fulfillment_flat_fee_link_ppm=500 +fulfillment_flat_fee_native_ppm=500 + +[VRFv2Plus.Performance] +test_duration = "2m" +rate_limit_unit_duration = "3s" +rps = 1 +use_existing_env = false + +[VRFv2Plus.NewEnv] +sub_funds_link = 1 +sub_funds_native = 1 +node_funds = 10 +node_sending_key_funding = 1000 + +[VRFv2Plus.ExistingEnv] +coordinator_address = "" +consumer_address = "" +sub_id = 1 +key_hash = "" +create_fund_subs_and_add_consumers = true +link_address = "" +sub_funds_link = 10 +node_sending_key_funding_min = 1 +node_sending_keys = [ + "", + "", + "", + "", + "", + "", +] \ No newline at end of file diff --git a/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml b/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml new file mode 100644 index 00000000000..5e187d9de3a --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml @@ -0,0 +1,161 @@ +# default config +[Common] +chainlink_node_funding = 0.1 + +[VRFv2Plus] +[VRFv2Plus.General] +max_gas_price_gwei = 10 +link_native_feed_response = 1000000000000000000 +minimum_confirmations = 3 +subscription_billing_type = "LINK_AND_NATIVE" +subscription_funding_amount_link = 5.0 +number_of_words = 3 +callback_gas_limit = 1000000 +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = 60000000000000000 +staleness_seconds = 86400 +gas_after_payment_calculation = 33825 +fulfilment_flat_fee_link_ppm_tier_1 = 500 +fulfilment_flat_fee_link_ppm_tier_2 = 500 +fulfilment_flat_fee_link_ppm_tier_3 = 500 +fulfilment_flat_fee_link_ppm_tier_4 = 500 +fulfilment_flat_fee_link_ppm_tier_5 = 500 +reqs_for_tier_2 = 0 +reqs_for_tier_3 = 0 +reqs_for_tier_4 = 0 +reqs_for_tier_5 = 0 +number_of_sub_to_create = 1 +randomness_request_count_per_request = 1 +randomness_request_count_per_request_deviation = 0 +random_words_fulfilled_event_timeout = "2m" +wrapped_gas_overhead = 50000 +coordinator_gas_overhead = 52000 +wrapper_premium_percentage = 25 +wrapper_max_number_of_words = 10 +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 10 +subscription_funding_amount_native=1 +fulfillment_flat_fee_link_ppm=500 +fulfillment_flat_fee_native_ppm=500 + +# load test specific config +[Load.VRFv2Plus] +[Load.VRFv2Plus.Common] +cancel_subs_after_test_run = true + +[Load.VRFv2Plus.General] +minimum_confirmations = 3 +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 + +[Load.VRFv2Plus.Performance] +test_duration = "2m" +# approx 60 RPM - 1 tx request with 3 rand requests in each tx every 3 seconds +rate_limit_unit_duration = "3s" +rps = 1 + +[Load.VRFv2Plus.NewEnv] +sub_funds_link = 1 +sub_funds_native = 1 +node_funds = 10 +node_sending_key_funding = 1000 + +[Load.VRFv2Plus.ExistingEnv] +sub_id = 1 +create_fund_subs_and_add_consumers = true +link_address = "" +sub_funds_link = 10 +node_sending_key_funding_min = 1 +node_sending_keys = [] + +# soak test specific config +[Soak.VRFv2Plus] +[Soak.VRFv2Plus.Common] +cancel_subs_after_test_run = true + +[Soak.VRFv2Plus.General] +minimum_confirmations = 3 +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 + +[Soak.VRFv2Plus.Performance] +test_duration = "2m" +# 10 RPM - 1 tx request with 1 rand request in each tx every 6 seconds +rate_limit_unit_duration = "6s" +rps = 1 +use_existing_env = false + +[Soak.VRFv2Plus.NewEnv] +sub_funds_link = 1 +sub_funds_native = 1 +node_funds = 10 +node_sending_key_funding = 1000 + +[Soak.VRFv2Plus.ExistingEnv] +sub_id = 1 +create_fund_subs_and_add_consumers = true +sub_funds_link = 10 +node_sending_key_funding_min = 1 +node_sending_keys = [] + +# spike test specific config +[Spike.VRFv2Plus] +[Spike.VRFv2Plus.Common] +cancel_subs_after_test_run = true + +[Spike.VRFv2Plus.General] +minimum_confirmations = 3 +randomness_request_count_per_request = 150 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 + +[Spike.VRFv2Plus.Performance] +test_duration = "2m" +# approx 150 RPM - 1 tx request with 150 rand requests in each tx every 60 seconds +rate_limit_unit_duration = "1m" +rps = 1 + +[Spike.VRFv2Plus.NewEnv] +sub_funds_link = 1 +sub_funds_native = 1 +node_funds = 10 +node_sending_key_funding = 1000 + +[Spike.VRFv2Plus.ExistingEnv] +sub_id = 1 +create_fund_subs_and_add_consumers = true +sub_funds_link = 10 +node_sending_key_funding_min = 1 +node_sending_keys = [] + +# stress test specific config +[Stress.VRFv2Plus] +[Stress.VRFv2Plus.Common] +cancel_subs_after_test_run = true + +[Stress.VRFv2Plus.General] +minimum_confirmations = 3 +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 + +[Stress.VRFv2Plus.Performance] +test_duration = "2m" +# approx 540 RPM - 3 tx requests per second with 4 rand requests in each tx +rate_limit_unit_duration = "1s" +rps = 3 + +[Stress.VRFv2Plus.NewEnv] +sub_funds_link = 1 +sub_funds_native = 1 +node_funds = 10 +node_sending_key_funding = 1000 + +[Stress.VRFv2Plus.ExistingEnv] +sub_id = 1 +create_fund_subs_and_add_consumers = true +sub_funds_link = 10 +node_sending_key_funding_min = 1 +node_sending_keys = [] \ No newline at end of file diff --git a/integration-tests/testreporters/keeper_benchmark.go b/integration-tests/testreporters/keeper_benchmark.go index 5db6cca3ec4..b878ff67a31 100644 --- a/integration-tests/testreporters/keeper_benchmark.go +++ b/integration-tests/testreporters/keeper_benchmark.go @@ -18,10 +18,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" ) -var ( - DashboardUrl = os.Getenv("GRAFANA_DASHBOARD_URL") -) - // KeeperBenchmarkTestReporter enables reporting on the keeper benchmark test type KeeperBenchmarkTestReporter struct { Reports []KeeperBenchmarkTestReport `json:"reports"` @@ -249,7 +245,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { } // SendSlackNotification sends a slack notification on the results of the test -func (k *KeeperBenchmarkTestReporter) SendSlackNotification(t *testing.T, slackClient *slack.Client) error { +func (k *KeeperBenchmarkTestReporter) SendSlackNotification(t *testing.T, slackClient *slack.Client, grafanaUrlProvider testreporters.GrafanaURLProvider) error { if slackClient == nil { slackClient = slack.New(testreporters.SlackAPIKey) } @@ -267,7 +263,17 @@ func (k *KeeperBenchmarkTestReporter) SendSlackNotification(t *testing.T, slackC return err } - formattedDashboardUrl := fmt.Sprintf("%s&from=%d&to=%d&var-namespace=%s&var-cl_node=chainlink-0-0", DashboardUrl, k.Summary.StartTime, k.Summary.EndTime, k.namespace) + grafanaUrl, err := grafanaUrlProvider.GetGrafanaBaseURL() + if err != nil { + return err + } + + dashboardUrl, err := grafanaUrlProvider.GetGrafanaDashboardURL() + if err != nil { + return err + } + + formattedDashboardUrl := fmt.Sprintf("%s%s?from=%d&to=%d&var-namespace=%s&var-cl_node=chainlink-0-0", grafanaUrl, dashboardUrl, k.Summary.StartTime, k.Summary.EndTime, k.namespace) log.Info().Str("Dashboard", formattedDashboardUrl).Msg("Dashboard URL") if err := testreporters.UploadSlackFile(slackClient, slack.FileUploadParameters{ diff --git a/integration-tests/testreporters/ocr.go b/integration-tests/testreporters/ocr.go index 31f5eeab1b9..9a9c4d0d4a0 100644 --- a/integration-tests/testreporters/ocr.go +++ b/integration-tests/testreporters/ocr.go @@ -235,7 +235,7 @@ func (o *OCRSoakTestReporter) WriteReport(folderLocation string) error { } // SendNotification sends a slack message to a slack webhook and uploads test artifacts -func (o *OCRSoakTestReporter) SendSlackNotification(t *testing.T, slackClient *slack.Client) error { +func (o *OCRSoakTestReporter) SendSlackNotification(t *testing.T, slackClient *slack.Client, _ testreporters.GrafanaURLProvider) error { if slackClient == nil { slackClient = slack.New(testreporters.SlackAPIKey) } diff --git a/integration-tests/testreporters/profile.go b/integration-tests/testreporters/profile.go index ab9dec138e4..464cfd685e7 100644 --- a/integration-tests/testreporters/profile.go +++ b/integration-tests/testreporters/profile.go @@ -54,7 +54,7 @@ func (c *ChainlinkProfileTestReporter) WriteReport(folderLocation string) error } // SendNotification hasn't been implemented for this test -func (c *ChainlinkProfileTestReporter) SendSlackNotification(_ *testing.T, _ *slack.Client) error { +func (c *ChainlinkProfileTestReporter) SendSlackNotification(_ *testing.T, _ *slack.Client, _ testreporters.GrafanaURLProvider) error { log.Warn().Msg("No Slack notification integration for Chainlink profile tests") return nil } diff --git a/integration-tests/testreporters/vrfv2.go b/integration-tests/testreporters/vrfv2.go index 2a72e4d91d0..4f4c7dc8fd1 100644 --- a/integration-tests/testreporters/vrfv2.go +++ b/integration-tests/testreporters/vrfv2.go @@ -3,15 +3,14 @@ package testreporters import ( "fmt" "math/big" - "os" + "strings" "testing" "time" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_config" - "github.com/slack-go/slack" "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink/integration-tests/types" ) type VRFV2TestReporter struct { @@ -21,7 +20,7 @@ type VRFV2TestReporter struct { AverageFulfillmentInMillions *big.Int SlowestFulfillment *big.Int FastestFulfillment *big.Int - Vrfv2Config *vrfv2_config.VRFV2Config + VRFv2TestConfig types.VRFv2TestConfig } func (o *VRFV2TestReporter) SetReportData( @@ -31,7 +30,7 @@ func (o *VRFV2TestReporter) SetReportData( AverageFulfillmentInMillions *big.Int, SlowestFulfillment *big.Int, FastestFulfillment *big.Int, - vrfv2Config vrfv2_config.VRFV2Config, + vrfv2TestConfig types.VRFv2TestConfig, ) { o.TestType = testType o.RequestCount = RequestCount @@ -39,7 +38,7 @@ func (o *VRFV2TestReporter) SetReportData( o.AverageFulfillmentInMillions = AverageFulfillmentInMillions o.SlowestFulfillment = SlowestFulfillment o.FastestFulfillment = FastestFulfillment - o.Vrfv2Config = &vrfv2Config + o.VRFv2TestConfig = vrfv2TestConfig } // SendSlackNotification sends a slack message to a slack webhook @@ -54,7 +53,14 @@ func (o *VRFV2TestReporter) SendSlackNotification(t *testing.T, slackClient *sla headerText = fmt.Sprintf(":x: VRF V2 %s Test FAILED :x:", o.TestType) } - messageBlocks := testreporters.SlackNotifyBlocks(headerText, os.Getenv("SELECTED_NETWORKS"), []string{ + perfCfg := o.VRFv2TestConfig.GetVRFv2Config().Performance + var sb strings.Builder + for _, n := range o.VRFv2TestConfig.GetNetworkConfig().SelectedNetworks { + sb.WriteString(n) + sb.WriteString(", ") + } + + messageBlocks := testreporters.SlackNotifyBlocks(headerText, sb.String(), []string{ fmt.Sprintf( "Summary\n"+ "Perf Test Type: %s\n"+ @@ -70,17 +76,17 @@ func (o *VRFV2TestReporter) SendSlackNotification(t *testing.T, slackClient *sla "RandomnessRequestCountPerRequest: %d\n"+ "RandomnessRequestCountPerRequestDeviation: %d\n", o.TestType, - o.Vrfv2Config.TestDuration.Truncate(time.Second).String(), - o.Vrfv2Config.UseExistingEnv, + perfCfg.TestDuration.Duration.Truncate(time.Second).String(), + *perfCfg.UseExistingEnv, o.RequestCount.String(), o.FulfilmentCount.String(), o.AverageFulfillmentInMillions.String(), o.SlowestFulfillment.String(), o.FastestFulfillment.String(), - o.Vrfv2Config.RPS, - o.Vrfv2Config.RateLimitUnitDuration.String(), - o.Vrfv2Config.RandomnessRequestCountPerRequest, - o.Vrfv2Config.RandomnessRequestCountPerRequestDeviation, + *perfCfg.RPS, + perfCfg.RateLimitUnitDuration.String(), + *o.VRFv2TestConfig.GetVRFv2Config().General.RandomnessRequestCountPerRequest, + *o.VRFv2TestConfig.GetVRFv2Config().General.RandomnessRequestCountPerRequestDeviation, ), }) diff --git a/integration-tests/testreporters/vrfv2plus.go b/integration-tests/testreporters/vrfv2plus.go index 21e4e52695a..8d384b07868 100644 --- a/integration-tests/testreporters/vrfv2plus.go +++ b/integration-tests/testreporters/vrfv2plus.go @@ -3,11 +3,11 @@ package testreporters import ( "fmt" "math/big" - "os" + "strings" "testing" "time" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config" + "github.com/smartcontractkit/chainlink/integration-tests/types" "github.com/slack-go/slack" @@ -21,7 +21,7 @@ type VRFV2PlusTestReporter struct { AverageFulfillmentInMillions *big.Int SlowestFulfillment *big.Int FastestFulfillment *big.Int - Vrfv2PlusConfig *vrfv2plus_config.VRFV2PlusConfig + VRFv2PlusTestConfig types.VRFv2PlusTestConfig } func (o *VRFV2PlusTestReporter) SetReportData( @@ -31,7 +31,7 @@ func (o *VRFV2PlusTestReporter) SetReportData( AverageFulfillmentInMillions *big.Int, SlowestFulfillment *big.Int, FastestFulfillment *big.Int, - vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + vtfv2PlusTestConfig types.VRFv2PlusTestConfig, ) { o.TestType = testType o.RequestCount = RequestCount @@ -39,11 +39,11 @@ func (o *VRFV2PlusTestReporter) SetReportData( o.AverageFulfillmentInMillions = AverageFulfillmentInMillions o.SlowestFulfillment = SlowestFulfillment o.FastestFulfillment = FastestFulfillment - o.Vrfv2PlusConfig = &vrfv2PlusConfig + o.VRFv2PlusTestConfig = vtfv2PlusTestConfig } // SendSlackNotification sends a slack message to a slack webhook -func (o *VRFV2PlusTestReporter) SendSlackNotification(t *testing.T, slackClient *slack.Client) error { +func (o *VRFV2PlusTestReporter) SendSlackNotification(t *testing.T, slackClient *slack.Client, vtfv2PlusTestConfig types.VRFv2PlusTestConfig) error { if slackClient == nil { slackClient = slack.New(testreporters.SlackAPIKey) } @@ -54,7 +54,8 @@ func (o *VRFV2PlusTestReporter) SendSlackNotification(t *testing.T, slackClient headerText = fmt.Sprintf(":x: VRF V2 Plus %s Test FAILED :x:", o.TestType) } - messageBlocks := testreporters.SlackNotifyBlocks(headerText, os.Getenv("SELECTED_NETWORKS"), []string{ + vrfv2lusConfig := o.VRFv2PlusTestConfig.GetVRFv2PlusConfig().Performance + messageBlocks := testreporters.SlackNotifyBlocks(headerText, strings.Join(vtfv2PlusTestConfig.GetNetworkConfig().SelectedNetworks, ","), []string{ fmt.Sprintf( "Summary\n"+ "Perf Test Type: %s\n"+ @@ -70,17 +71,17 @@ func (o *VRFV2PlusTestReporter) SendSlackNotification(t *testing.T, slackClient "RandomnessRequestCountPerRequest: %d\n"+ "RandomnessRequestCountPerRequestDeviation: %d\n", o.TestType, - o.Vrfv2PlusConfig.TestDuration.Truncate(time.Second).String(), - o.Vrfv2PlusConfig.UseExistingEnv, + vrfv2lusConfig.TestDuration.Duration.Truncate(time.Second).String(), + *vrfv2lusConfig.UseExistingEnv, o.RequestCount.String(), o.FulfilmentCount.String(), o.AverageFulfillmentInMillions.String(), o.SlowestFulfillment.String(), o.FastestFulfillment.String(), - o.Vrfv2PlusConfig.RPS, - o.Vrfv2PlusConfig.RateLimitUnitDuration.String(), - o.Vrfv2PlusConfig.RandomnessRequestCountPerRequest, - o.Vrfv2PlusConfig.RandomnessRequestCountPerRequestDeviation, + *vrfv2lusConfig.RPS, + vrfv2lusConfig.RateLimitUnitDuration.String(), + *o.VRFv2PlusTestConfig.GetVRFv2PlusConfig().General.RandomnessRequestCountPerRequest, + *o.VRFv2PlusTestConfig.GetVRFv2PlusConfig().General.RandomnessRequestCountPerRequestDeviation, ), }) diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go index 575ed3e7de5..1330ea291b8 100644 --- a/integration-tests/testsetups/keeper_benchmark.go +++ b/integration-tests/testsetups/keeper_benchmark.go @@ -38,6 +38,7 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" + tt "github.com/smartcontractkit/chainlink/integration-tests/types" ) // KeeperBenchmarkTest builds a test to check that chainlink nodes are able to upkeep a specified amount of Upkeep @@ -59,6 +60,7 @@ type KeeperBenchmarkTest struct { namespace string chainlinkNodes []*client.ChainlinkK8sClient chainClient blockchain.EVMClient + testConfig tt.KeeperBenchmarkTestConfig contractDeployer contracts.ContractDeployer linkToken contracts.LinkToken @@ -113,13 +115,14 @@ func NewKeeperBenchmarkTest(t *testing.T, inputs KeeperBenchmarkTestInputs) *Kee } // Setup prepares contracts for the test -func (k *KeeperBenchmarkTest) Setup(env *environment.Environment) { +func (k *KeeperBenchmarkTest) Setup(env *environment.Environment, config tt.KeeperBenchmarkTestConfig) { startTime := time.Now() k.TestReporter.Summary.StartTime = startTime.UnixMilli() k.ensureInputValues() k.env = env k.namespace = k.env.Cfg.Namespace inputs := k.Inputs + k.testConfig = config k.keeperRegistries = make([]contracts.KeeperRegistry, len(inputs.RegistryVersions)) k.keeperRegistrars = make([]contracts.KeeperRegistrar, len(inputs.RegistryVersions)) @@ -202,7 +205,7 @@ func (k *KeeperBenchmarkTest) Setup(env *environment.Environment) { } k.log.Info().Str("Setup Time", time.Since(startTime).String()).Msg("Finished Keeper Benchmark Test Setup") - err = k.SendSlackNotification(nil) + err = k.SendSlackNotification(nil, config) if err != nil { k.log.Warn().Msg("Sending test start slack notification failed") } @@ -405,9 +408,10 @@ func (k *KeeperBenchmarkTest) TearDownVals(t *testing.T) ( string, []*client.ChainlinkK8sClient, reportModel.TestReporter, + reportModel.GrafanaURLProvider, blockchain.EVMClient, ) { - return t, k.namespace, k.chainlinkNodes, &k.TestReporter, k.chainClient + return t, k.namespace, k.chainlinkNodes, &k.TestReporter, k.testConfig, k.chainClient } // ********************* @@ -571,13 +575,23 @@ func (k *KeeperBenchmarkTest) ensureInputValues() { } } -func (k *KeeperBenchmarkTest) SendSlackNotification(slackClient *slack.Client) error { +func (k *KeeperBenchmarkTest) SendSlackNotification(slackClient *slack.Client, config tt.KeeperBenchmarkTestConfig) error { if slackClient == nil { slackClient = slack.New(reportModel.SlackAPIKey) } + grafanaUrl, err := config.GetGrafanaBaseURL() + if err != nil { + return err + } + + dashboardUrl, err := config.GetGrafanaDashboardURL() + if err != nil { + return err + } + headerText := ":white_check_mark: Automation Benchmark Test STARTED :white_check_mark:" - formattedDashboardUrl := fmt.Sprintf("%s&from=%d&to=%s&var-namespace=%s&var-cl_node=chainlink-0-0", testreporters.DashboardUrl, k.TestReporter.Summary.StartTime, "now", k.env.Cfg.Namespace) + formattedDashboardUrl := fmt.Sprintf("%s%s?from=%d&to=%s&var-namespace=%s&var-cl_node=chainlink-0-0", grafanaUrl, dashboardUrl, k.TestReporter.Summary.StartTime, "now", k.env.Cfg.Namespace) log.Info().Str("Dashboard", formattedDashboardUrl).Msg("Dashboard URL") notificationBlocks := []slack.Block{} diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index f7e0e65d36d..a2e2fe42bae 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -10,7 +10,6 @@ import ( "os" "os/signal" "sort" - "strconv" "strings" "syscall" "testing" @@ -19,7 +18,6 @@ import ( geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/kelseyhightower/envconfig" "github.com/pelletier/go-toml/v2" "github.com/rs/zerolog" "github.com/stretchr/testify/require" @@ -29,6 +27,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" @@ -44,6 +43,9 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" + tt "github.com/smartcontractkit/chainlink/integration-tests/types" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) const ( @@ -53,7 +55,7 @@ const ( // OCRSoakTest defines a typical OCR soak test type OCRSoakTest struct { - Inputs *OCRSoakTestInputs + Config *tc.TestConfig TestReporter testreporters.OCRSoakTestReporter OperatorForwarderFlow bool @@ -80,51 +82,18 @@ type OCRSoakTest struct { ocrV2InstanceMap map[string]contracts.OffchainAggregatorV2 // address : instance } -// OCRSoakTestInputs define required inputs to run an OCR soak test -type OCRSoakTestInputs struct { - OCRVersion string `envconfig:"OCR_VERSION" default:"1"` // Version of OCR to use (1 or 2) - TestDuration time.Duration `envconfig:"TEST_DURATION" default:"15m"` // How long to run the test for - NumberOfContracts int `envconfig:"NUMBER_CONTRACTS" default:"2"` // Number of OCR contracts to launch - ChainlinkNodeFunding float64 `envconfig:"CHAINLINK_NODE_FUNDING" default:".1"` // Amount of native currency to fund each chainlink node with - bigChainlinkNodeFunding *big.Float // Convenience conversions for funding - TimeBetweenRounds time.Duration `envconfig:"TIME_BETWEEN_ROUNDS" default:"1m"` // How long to wait before starting a new round; controls frequency of rounds -} - -func (i OCRSoakTestInputs) setForRemoteRunner() { - os.Setenv("TEST_OCR_VERSION", i.OCRVersion) - os.Setenv("TEST_OCR_TEST_DURATION", i.TestDuration.String()) - os.Setenv("TEST_OCR_NUMBER_CONTRACTS", fmt.Sprint(i.NumberOfContracts)) - os.Setenv("TEST_OCR_CHAINLINK_NODE_FUNDING", strconv.FormatFloat(i.ChainlinkNodeFunding, 'f', -1, 64)) - os.Setenv("TEST_OCR_TIME_BETWEEN_ROUNDS", i.TimeBetweenRounds.String()) - - selectedNetworks := strings.Split(os.Getenv("SELECTED_NETWORKS"), ",") - for _, networkPrefix := range selectedNetworks { - urlEnv := fmt.Sprintf("%s_URLS", networkPrefix) - httpEnv := fmt.Sprintf("%s_HTTP_URLS", networkPrefix) - os.Setenv(fmt.Sprintf("TEST_%s", urlEnv), os.Getenv(urlEnv)) - os.Setenv(fmt.Sprintf("TEST_%s", httpEnv), os.Getenv(httpEnv)) - } -} - // NewOCRSoakTest creates a new OCR soak test to setup and run -func NewOCRSoakTest(t *testing.T, forwarderFlow bool) (*OCRSoakTest, error) { - var testInputs OCRSoakTestInputs - err := envconfig.Process("OCR", &testInputs) - if err != nil { - return nil, err - } - testInputs.setForRemoteRunner() - +func NewOCRSoakTest(t *testing.T, config *tc.TestConfig, forwarderFlow bool) (*OCRSoakTest, error) { test := &OCRSoakTest{ - Inputs: &testInputs, + Config: config, OperatorForwarderFlow: forwarderFlow, TestReporter: testreporters.OCRSoakTestReporter{ - OCRVersion: testInputs.OCRVersion, + OCRVersion: *config.OCR.Soak.OCRVersion, StartTime: time.Now(), }, t: t, startTime: time.Now(), - timeLeft: testInputs.TestDuration, + timeLeft: config.OCR.Common.TestDuration.Duration, log: logging.GetTestLogger(t), ocrRoundStates: make([]*testreporters.OCRRoundState, 0), ocrV1InstanceMap: make(map[string]contracts.OffchainAggregator), @@ -134,9 +103,9 @@ func NewOCRSoakTest(t *testing.T, forwarderFlow bool) (*OCRSoakTest, error) { } // DeployEnvironment deploys the test environment, starting all Chainlink nodes and other components for the test -func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) { - network := networks.MustGetSelectedNetworksFromEnv()[0] // Environment currently being used to soak test on - nsPre := fmt.Sprintf("soak-ocr-v%s-", o.Inputs.OCRVersion) +func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string, ocrTestConfig tt.OcrTestConfig) { + network := networks.MustGetSelectedNetworkConfig(ocrTestConfig.GetNetworkConfig())[0] // Environment currently being used to soak test on + nsPre := fmt.Sprintf("soak-ocr-v%s-", *ocrTestConfig.GetOCRConfig().Soak.OCRVersion) if o.OperatorForwarderFlow { nsPre = fmt.Sprintf("%sforwarder-", nsPre) } @@ -149,18 +118,24 @@ func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) { } var conf string - if o.Inputs.OCRVersion == "1" { + if *ocrTestConfig.GetOCRConfig().Soak.OCRVersion == "1" { conf = config.BaseOCR1Config - } else if o.Inputs.OCRVersion == "2" { + } else if *ocrTestConfig.GetOCRConfig().Soak.OCRVersion == "2" { conf = config.BaseOCR2Config } - cd := chainlink.New(0, map[string]any{ + + var overrideFn = func(_ interface{}, target interface{}) { + ctf_config.MustConfigOverrideChainlinkVersion(ocrTestConfig.GetChainlinkImageConfig(), target) + ctf_config.MightConfigOverridePyroscopeKey(ocrTestConfig.GetPyroscopeConfig(), target) + } + + cd := chainlink.NewWithOverride(0, map[string]any{ "replicas": 6, - "toml": networks.AddNetworkDetailedConfig(conf, customChainlinkNetworkTOML, network), + "toml": networks.AddNetworkDetailedConfig(conf, ocrTestConfig.GetPyroscopeConfig(), customChainlinkNetworkTOML, network), "db": map[string]any{ "stateful": true, // stateful DB by default for soak tests }, - }) + }, ocrTestConfig.GetChainlinkImageConfig(), overrideFn) testEnvironment := environment.New(baseEnvironmentConfig). AddHelm(mockservercfg.New(nil)). @@ -178,9 +153,9 @@ func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) { } // LoadEnvironment loads an existing test environment using the provided URLs -func (o *OCRSoakTest) LoadEnvironment(chainlinkURLs []string, mockServerURL string) { +func (o *OCRSoakTest) LoadEnvironment(chainlinkURLs []string, mockServerURL string, ocrTestConfig tt.OcrTestConfig) { var ( - network = networks.MustGetSelectedNetworksFromEnv()[0] + network = networks.MustGetSelectedNetworkConfig(ocrTestConfig.GetNetworkConfig())[0] err error ) o.chainClient, err = blockchain.ConnectEVMClient(network, o.log) @@ -197,10 +172,10 @@ func (o *OCRSoakTest) Environment() *environment.Environment { return o.testEnvironment } -func (o *OCRSoakTest) Setup() { +func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { var ( err error - network = networks.MustGetSelectedNetworksFromEnv()[0] + network = networks.MustGetSelectedNetworkConfig(ocrTestConfig.GetNetworkConfig())[0] ) // Environment currently being used to soak test on @@ -221,7 +196,8 @@ func (o *OCRSoakTest) Setup() { require.NoError(o.t, err, "Deploying Link Token Contract shouldn't fail") // Fund Chainlink nodes, excluding the bootstrap node - err = actions.FundChainlinkNodes(o.workerNodes, o.chainClient, o.Inputs.bigChainlinkNodeFunding) + o.log.Info().Float64("ETH amount per node", *o.Config.Common.ChainlinkNodeFunding).Msg("Funding Chainlink nodes") + err = actions.FundChainlinkNodes(o.workerNodes, o.chainClient, big.NewFloat(*o.Config.Common.ChainlinkNodeFunding)) require.NoError(o.t, err, "Error funding Chainlink nodes") if o.OperatorForwarderFlow { @@ -244,23 +220,23 @@ func (o *OCRSoakTest) Setup() { o.ocrV1Instances = actions.DeployOCRContractsForwarderFlow( o.t, - o.Inputs.NumberOfContracts, + *o.Config.OCR.Soak.NumberOfContracts, linkTokenContract, contractDeployer, o.workerNodes, authorizedForwarders, o.chainClient, ) - } else if o.Inputs.OCRVersion == "1" { + } else if *ocrTestConfig.GetOCRConfig().Soak.OCRVersion == "1" { o.ocrV1Instances, err = actions.DeployOCRContracts( - o.Inputs.NumberOfContracts, + *o.Config.OCR.Soak.NumberOfContracts, linkTokenContract, contractDeployer, o.workerNodes, o.chainClient, ) require.NoError(o.t, err) - } else if o.Inputs.OCRVersion == "2" { + } else if *ocrTestConfig.GetOCRConfig().Soak.OCRVersion == "2" { var transmitters []string for _, node := range o.workerNodes { nodeAddress, err := node.PrimaryEthAddress() @@ -269,7 +245,7 @@ func (o *OCRSoakTest) Setup() { } ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() o.ocrV2Instances, err = actions.DeployOCRv2Contracts( - o.Inputs.NumberOfContracts, + *ocrTestConfig.GetOCRConfig().Soak.NumberOfContracts, linkTokenContract, contractDeployer, transmitters, @@ -285,11 +261,11 @@ func (o *OCRSoakTest) Setup() { err = o.chainClient.WaitForEvents() require.NoError(o.t, err, "Error waiting for OCR contracts to be deployed") - if o.Inputs.OCRVersion == "1" { + if *ocrTestConfig.GetOCRConfig().Soak.OCRVersion == "1" { for _, ocrInstance := range o.ocrV1Instances { o.ocrV1InstanceMap[ocrInstance.Address()] = ocrInstance } - } else if o.Inputs.OCRVersion == "2" { + } else if *ocrTestConfig.GetOCRConfig().Soak.OCRVersion == "2" { for _, ocrInstance := range o.ocrV2Instances { o.ocrV2InstanceMap[ocrInstance.Address()] = ocrInstance } @@ -300,6 +276,9 @@ func (o *OCRSoakTest) Setup() { // Run starts the OCR soak test func (o *OCRSoakTest) Run() { + config, err := tc.GetConfig("soak", tc.OCR) + require.NoError(o.t, err, "Error getting config") + ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) latestBlockNum, err := o.chainClient.LatestBlockNumber(ctx) cancel() @@ -309,21 +288,21 @@ func (o *OCRSoakTest) Run() { startingValue := 5 if o.OperatorForwarderFlow { actions.CreateOCRJobsWithForwarder(o.t, o.ocrV1Instances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.chainClient.GetChainID().String()) - } else if o.Inputs.OCRVersion == "1" { + } else if *config.OCR.Soak.OCRVersion == "1" { err := actions.CreateOCRJobs(o.ocrV1Instances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.chainClient.GetChainID().String()) require.NoError(o.t, err, "Error creating OCR jobs") - } else if o.Inputs.OCRVersion == "2" { + } else if *config.OCR.Soak.OCRVersion == "2" { err := actions.CreateOCRv2Jobs(o.ocrV2Instances, o.bootstrapNode, o.workerNodes, o.mockServer, startingValue, o.chainClient.GetChainID().Uint64(), o.OperatorForwarderFlow) require.NoError(o.t, err, "Error creating OCR jobs") } o.log.Info(). - Str("Test Duration", o.Inputs.TestDuration.Truncate(time.Second).String()). - Int("Number of OCR Contracts", o.Inputs.NumberOfContracts). - Str("OCR Version", o.Inputs.OCRVersion). + Str("Test Duration", o.Config.OCR.Common.TestDuration.Duration.Truncate(time.Second).String()). + Int("Number of OCR Contracts", *config.OCR.Soak.NumberOfContracts). + Str("OCR Version", *config.OCR.Soak.OCRVersion). Msg("Starting OCR Soak Test") - o.testLoop(o.Inputs.TestDuration, startingValue) + o.testLoop(o.Config.OCR.Common.TestDuration.Duration, startingValue) o.complete() } @@ -333,9 +312,10 @@ func (o *OCRSoakTest) TearDownVals(t *testing.T) ( string, []*client.ChainlinkK8sClient, reportModel.TestReporter, + reportModel.GrafanaURLProvider, blockchain.EVMClient, ) { - return t, o.namespace, append(o.workerNodes, o.bootstrapNode), &o.TestReporter, o.chainClient + return t, o.namespace, append(o.workerNodes, o.bootstrapNode), &o.TestReporter, o.Config, o.chainClient } // ********************* @@ -375,9 +355,9 @@ func (o *OCRSoakTest) SaveState() error { StartingBlockNum: o.startingBlockNum, StartTime: o.startTime, TimeRunning: time.Since(o.startTime), - TestDuration: o.Inputs.TestDuration, + TestDuration: o.Config.OCR.Common.TestDuration.Duration, OCRContractAddresses: ocrAddresses, - OCRVersion: o.Inputs.OCRVersion, + OCRVersion: *o.Config.OCR.Soak.OCRVersion, ChainURL: o.chainClient.GetNetworkConfig().URL, MockServerURL: "http://mockserver:1080", // TODO: Make this dynamic @@ -426,15 +406,16 @@ func (o *OCRSoakTest) LoadState() error { OCRVersion: testState.OCRVersion, StartTime: testState.StartTime, } + duration := blockchain.StrDuration{Duration: testState.TestDuration} o.ocrRoundStates = testState.OCRRoundStates o.testIssues = testState.TestIssues - o.Inputs.TestDuration = testState.TestDuration + o.Config.OCR.Common.TestDuration = &duration o.timeLeft = testState.TestDuration - testState.TimeRunning o.startTime = testState.StartTime o.startingBlockNum = testState.StartingBlockNum - o.Inputs.OCRVersion = testState.OCRVersion + o.Config.OCR.Soak.OCRVersion = &testState.OCRVersion - network := networks.MustGetSelectedNetworksFromEnv()[0] + network := networks.MustGetSelectedNetworkConfig(o.Config.Network)[0] o.chainClient, err = blockchain.ConnectEVMClient(network, o.log) if err != nil { return err @@ -488,13 +469,13 @@ func (o *OCRSoakTest) Resume() { Message: "Test Resumed", }) o.log.Info(). - Str("Total Duration", o.Inputs.TestDuration.String()). + Str("Total Duration", o.Config.OCR.Common.TestDuration.String()). Str("Time Left", o.timeLeft.String()). Msg("Resuming OCR Soak Test") - ocrAddresses := make([]common.Address, o.Inputs.NumberOfContracts) + ocrAddresses := make([]common.Address, *o.Config.OCR.Soak.NumberOfContracts) - if o.Inputs.OCRVersion == "1" { + if *o.Config.OCR.Soak.OCRVersion == "1" { for i, ocrInstance := range o.ocrV1Instances { ocrAddresses[i] = common.HexToAddress(ocrInstance.Address()) } @@ -505,7 +486,7 @@ func (o *OCRSoakTest) Resume() { Topics: [][]common.Hash{{contractABI.Events["AnswerUpdated"].ID}}, FromBlock: big.NewInt(0).SetUint64(o.startingBlockNum), } - } else if o.Inputs.OCRVersion == "2" { + } else if *o.Config.OCR.Soak.OCRVersion == "2" { for i, ocrInstance := range o.ocrV2Instances { ocrAddresses[i] = common.HexToAddress(ocrInstance.Address()) } @@ -569,7 +550,7 @@ func (o *OCRSoakTest) testLoop(testDuration time.Duration, newValue int) { return case <-newRoundTrigger.C: err := o.triggerNewRound(newValue) - timerReset := o.Inputs.TimeBetweenRounds + timerReset := o.Config.OCR.Soak.TimeBetweenRounds.Duration if err != nil { timerReset = time.Second * 5 o.log.Error().Err(err). @@ -641,7 +622,7 @@ func (o *OCRSoakTest) observeOCREvents() error { for { select { case event := <-eventLogs: - if o.Inputs.OCRVersion == "1" { + if *o.Config.OCR.Soak.OCRVersion == "1" { answerUpdated, err := o.ocrV1Instances[0].ParseEventAnswerUpdated(event) if err != nil { o.log.Warn(). @@ -657,7 +638,7 @@ func (o *OCRSoakTest) observeOCREvents() error { Uint64("Round ID", answerUpdated.RoundId.Uint64()). Int64("Answer", answerUpdated.Current.Int64()). Msg("Answer Updated Event") - } else if o.Inputs.OCRVersion == "2" { + } else if *o.Config.OCR.Soak.OCRVersion == "2" { answerUpdated, err := o.ocrV2Instances[0].ParseEventAnswerUpdated(event) if err != nil { o.log.Warn(). @@ -704,9 +685,9 @@ func (o *OCRSoakTest) triggerNewRound(newValue int) error { } var err error - if o.Inputs.OCRVersion == "1" { + if *o.Config.OCR.Soak.OCRVersion == "1" { err = actions.SetAllAdapterResponsesToTheSameValue(newValue, o.ocrV1Instances, o.workerNodes, o.mockServer) - } else if o.Inputs.OCRVersion == "2" { + } else if *o.Config.OCR.Soak.OCRVersion == "2" { err = actions.SetOCR2AllAdapterResponsesToTheSameValue(newValue, o.ocrV2Instances, o.workerNodes, o.mockServer) } if err != nil { @@ -718,11 +699,11 @@ func (o *OCRSoakTest) triggerNewRound(newValue int) error { Answer: int64(newValue), FoundEvents: make(map[string][]*testreporters.FoundEvent), } - if o.Inputs.OCRVersion == "1" { + if *o.Config.OCR.Soak.OCRVersion == "1" { for _, ocrInstance := range o.ocrV1Instances { expectedState.FoundEvents[ocrInstance.Address()] = make([]*testreporters.FoundEvent, 0) } - } else if o.Inputs.OCRVersion == "2" { + } else if *o.Config.OCR.Soak.OCRVersion == "2" { for _, ocrInstance := range o.ocrV2Instances { expectedState.FoundEvents[ocrInstance.Address()] = make([]*testreporters.FoundEvent, 0) } @@ -763,7 +744,7 @@ func (o *OCRSoakTest) collectEvents() error { sortedFoundEvents := make([]*testreporters.FoundEvent, 0) for _, event := range contractEvents { - if o.Inputs.OCRVersion == "1" { + if *o.Config.OCR.Soak.OCRVersion == "1" { answerUpdated, err := o.ocrV1Instances[0].ParseEventAnswerUpdated(event) if err != nil { return fmt.Errorf("error parsing EventAnswerUpdated for event: %v, %w", event, err) @@ -775,7 +756,7 @@ func (o *OCRSoakTest) collectEvents() error { RoundID: answerUpdated.RoundId.Uint64(), BlockNumber: event.BlockNumber, }) - } else if o.Inputs.OCRVersion == "2" { + } else if *o.Config.OCR.Soak.OCRVersion == "2" { answerUpdated, err := o.ocrV2Instances[0].ParseEventAnswerUpdated(event) if err != nil { return fmt.Errorf("error parsing EventAnswerUpdated for event: %v, %w", event, err) @@ -819,26 +800,26 @@ func (o *OCRSoakTest) collectEvents() error { // ensureValues ensures that all values needed to run the test are present func (o *OCRSoakTest) ensureInputValues() error { - inputs := o.Inputs - if inputs.OCRVersion != "1" && inputs.OCRVersion != "2" { - return fmt.Errorf("OCR version must be 1 or 2, found %s", inputs.OCRVersion) + ocrConfig := o.Config.OCR.Soak + if *ocrConfig.OCRVersion != "1" && *ocrConfig.OCRVersion != "2" { + return fmt.Errorf("OCR version must be 1 or 2, found %s", *ocrConfig.OCRVersion) } - if inputs.NumberOfContracts <= 0 { - return fmt.Errorf("Number of OCR contracts must be greater than 0, found %d", inputs.NumberOfContracts) + if ocrConfig.NumberOfContracts != nil && *ocrConfig.NumberOfContracts <= 0 { + return fmt.Errorf("Number of OCR contracts must be set and greater than 0, found %d", ocrConfig.NumberOfContracts) } - if inputs.ChainlinkNodeFunding <= 0 { - return fmt.Errorf("Chainlink node funding must be greater than 0, found %f", inputs.ChainlinkNodeFunding) + if o.Config.Common.ChainlinkNodeFunding != nil && *o.Config.Common.ChainlinkNodeFunding <= 0 { + return fmt.Errorf("Chainlink node funding must be greater than 0, found %f", *o.Config.Common.ChainlinkNodeFunding) } - if inputs.TestDuration <= time.Minute { - return fmt.Errorf("Test duration must be greater than 1 minute, found %s", inputs.TestDuration.String()) + if o.Config.OCR.Common.TestDuration != nil && o.Config.OCR.Common.TestDuration.Duration <= time.Minute { + return fmt.Errorf("Test duration must be greater than 1 minute, found %s", o.Config.OCR.Common.TestDuration) } - if inputs.TimeBetweenRounds >= time.Hour { - return fmt.Errorf("Time between rounds must be less than 1 hour, found %s", inputs.TimeBetweenRounds.String()) + if ocrConfig.TimeBetweenRounds != nil && ocrConfig.TimeBetweenRounds.Duration >= time.Hour { + return fmt.Errorf("Time between rounds must be less than 1 hour, found %s", ocrConfig.TimeBetweenRounds) } - if inputs.TimeBetweenRounds < time.Second*30 { - return fmt.Errorf("Time between rounds must be greater or equal to 30 seconds, found %s", inputs.TimeBetweenRounds.String()) + if ocrConfig.TimeBetweenRounds != nil && ocrConfig.TimeBetweenRounds.Duration < time.Second*30 { + return fmt.Errorf("Time between rounds must be greater or equal to 30 seconds, found %s", ocrConfig.TimeBetweenRounds) } - o.Inputs.bigChainlinkNodeFunding = big.NewFloat(inputs.ChainlinkNodeFunding) + return nil } diff --git a/integration-tests/types/testconfigs.go b/integration-tests/types/testconfigs.go new file mode 100644 index 00000000000..0c704f0cd7b --- /dev/null +++ b/integration-tests/types/testconfigs.go @@ -0,0 +1,44 @@ +package types + +import ( + "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" +) + +type VRFv2TestConfig interface { + tc.CommonTestConfig + tc.GlobalTestConfig + tc.VRFv2TestConfig +} + +type VRFv2PlusTestConfig interface { + tc.CommonTestConfig + tc.GlobalTestConfig + tc.VRFv2PlusTestConfig +} + +type FunctionsTestConfig interface { + tc.CommonTestConfig + tc.GlobalTestConfig + tc.FunctionsTestConfig +} + +type AutomationTestConfig interface { + tc.GlobalTestConfig + tc.CommonTestConfig + tc.UpgradeableChainlinkTestConfig +} + +type KeeperBenchmarkTestConfig interface { + tc.GlobalTestConfig + tc.CommonTestConfig + tc.KeeperTestConfig + tc.NamedConfiguration + testreporters.GrafanaURLProvider +} + +type OcrTestConfig interface { + tc.GlobalTestConfig + tc.CommonTestConfig + tc.OcrTestConfig +} diff --git a/integration-tests/universal/log_poller/config.go b/integration-tests/universal/log_poller/config.go deleted file mode 100644 index b8773d836f6..00000000000 --- a/integration-tests/universal/log_poller/config.go +++ /dev/null @@ -1,249 +0,0 @@ -package logpoller - -import ( - "fmt" - "os" - "strconv" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/pelletier/go-toml/v2" - "github.com/rs/zerolog/log" - - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" -) - -const ( - DefaultConfigFilename = "config.toml" - - ErrReadPerfConfig = "failed to read TOML config for performance tests" - ErrUnmarshalPerfConfig = "failed to unmarshal TOML config for performance tests" -) - -type GeneratorType = string - -const ( - GeneratorType_WASP = "wasp" - GeneratorType_Looped = "looped" -) - -type Config struct { - General *General `toml:"general"` - ChaosConfig *ChaosConfig `toml:"chaos"` - Wasp *WaspConfig `toml:"wasp"` - LoopedConfig *LoopedConfig `toml:"looped"` -} - -type LoopedConfig struct { - ContractConfig `toml:"contract"` - FuzzConfig `toml:"fuzz"` -} - -type ContractConfig struct { - ExecutionCount int `toml:"execution_count"` -} - -type FuzzConfig struct { - MinEmitWaitTimeMs int `toml:"min_emit_wait_time_ms"` - MaxEmitWaitTimeMs int `toml:"max_emit_wait_time_ms"` -} - -type General struct { - Generator string `toml:"generator"` - EventsToEmit []abi.Event `toml:"-"` - Contracts int `toml:"contracts"` - EventsPerTx int `toml:"events_per_tx"` - UseFinalityTag bool `toml:"use_finality_tag"` -} - -type ChaosConfig struct { - ExperimentCount int `toml:"experiment_count"` - TargetComponent string `toml:"target_component"` -} - -type WaspConfig struct { - Load *Load `toml:"load"` -} - -type Load struct { - RPS int64 `toml:"rps"` - LPS int64 `toml:"lps"` - RateLimitUnitDuration *commonconfig.Duration `toml:"rate_limit_unit_duration"` - Duration *commonconfig.Duration `toml:"duration"` - CallTimeout *commonconfig.Duration `toml:"call_timeout"` -} - -func ReadConfig(configName string) (*Config, error) { - var cfg *Config - d, err := os.ReadFile(configName) - if err != nil { - return nil, fmt.Errorf("%w: %s", err, ErrReadPerfConfig) - } - err = toml.Unmarshal(d, &cfg) - if err != nil { - return nil, fmt.Errorf("%w: %s", err, ErrUnmarshalPerfConfig) - } - - if err := cfg.validate(); err != nil { - return nil, err - } - - log.Debug().Interface("Config", cfg).Msg("Parsed config") - return cfg, nil -} - -func (c *Config) OverrideFromEnv() error { - if contr := os.Getenv("CONTRACTS"); contr != "" { - c.General.Contracts = mustParseInt(contr) - } - - if eventsPerTx := os.Getenv("EVENTS_PER_TX"); eventsPerTx != "" { - c.General.EventsPerTx = mustParseInt(eventsPerTx) - } - - if useFinalityTag := os.Getenv("USE_FINALITY_TAG"); useFinalityTag != "" { - c.General.UseFinalityTag = mustParseBool(useFinalityTag) - } - - if duration := os.Getenv("LOAD_DURATION"); duration != "" { - d, err := commonconfig.ParseDuration(duration) - if err != nil { - return err - } - - if c.General.Generator == GeneratorType_WASP { - c.Wasp.Load.Duration = &d - } else { - // this is completely arbitrary and practice shows that even with this values - // test executes much longer than specified, probably due to network latency - c.LoopedConfig.FuzzConfig.MinEmitWaitTimeMs = 400 - c.LoopedConfig.FuzzConfig.MaxEmitWaitTimeMs = 600 - // divide by 4 based on past runs, but we should do it in a better way - c.LoopedConfig.ContractConfig.ExecutionCount = int(d.Duration().Seconds() / 4) - } - } - - return nil -} - -func (c *Config) validate() error { - if c.General == nil { - return fmt.Errorf("General config is nil") - } - - err := c.General.validate() - if err != nil { - return fmt.Errorf("General config validation failed: %w", err) - } - - switch c.General.Generator { - case GeneratorType_WASP: - if c.Wasp == nil { - return fmt.Errorf("wasp config is nil") - } - if c.Wasp.Load == nil { - return fmt.Errorf("wasp load config is nil") - } - - err = c.Wasp.validate() - if err != nil { - return fmt.Errorf("wasp config validation failed: %w", err) - } - case GeneratorType_Looped: - if c.LoopedConfig == nil { - return fmt.Errorf("looped config is nil") - } - - err = c.LoopedConfig.validate() - if err != nil { - return fmt.Errorf("looped config validation failed: %w", err) - } - default: - return fmt.Errorf("unknown generator type: %s", c.General.Generator) - } - - return nil -} - -func (g *General) validate() error { - if g.Generator == "" { - return fmt.Errorf("generator is empty") - } - - if g.Contracts == 0 { - return fmt.Errorf("contracts is 0, but must be > 0") - } - - if g.EventsPerTx == 0 { - return fmt.Errorf("events_per_tx is 0, but must be > 0") - } - - return nil -} - -func (w *WaspConfig) validate() error { - if w.Load == nil { - return fmt.Errorf("Load config is nil") - } - - err := w.Load.validate() - if err != nil { - return fmt.Errorf("Load config validation failed: %w", err) - } - - return nil -} - -func (l *Load) validate() error { - if l.RPS == 0 && l.LPS == 0 { - return fmt.Errorf("either RPS or LPS needs to be set") - } - - if l.RPS != 0 && l.LPS != 0 { - return fmt.Errorf("only one of RPS or LPS can be set") - } - - if l.Duration == nil { - return fmt.Errorf("duration is nil") - } - - if l.CallTimeout == nil { - return fmt.Errorf("call_timeout is nil") - } - if l.RateLimitUnitDuration == nil { - return fmt.Errorf("rate_limit_unit_duration is nil") - } - - return nil -} - -func (l *LoopedConfig) validate() error { - if l.ExecutionCount == 0 { - return fmt.Errorf("execution_count is 0, but must be > 0") - } - - if l.MinEmitWaitTimeMs == 0 { - return fmt.Errorf("min_emit_wait_time_ms is 0, but must be > 0") - } - - if l.MaxEmitWaitTimeMs == 0 { - return fmt.Errorf("max_emit_wait_time_ms is 0, but must be > 0") - } - - return nil -} - -func mustParseInt(s string) int { - i, err := strconv.Atoi(s) - if err != nil { - panic(err) - } - return i -} - -func mustParseBool(s string) bool { - b, err := strconv.ParseBool(s) - if err != nil { - panic(err) - } - return b -} diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 597b82ef6c3..db7eaee625b 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -44,6 +44,9 @@ import ( le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" core_logger "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" + + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + lp_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/log_poller" ) var ( @@ -153,7 +156,7 @@ type ExpectedFilter struct { } // GetExpectedFilters returns a slice of ExpectedFilter structs based on the provided log emitters and config -func GetExpectedFilters(logEmitters []*contracts.LogEmitter, cfg *Config) []ExpectedFilter { +func GetExpectedFilters(logEmitters []*contracts.LogEmitter, cfg *lp_config.Config) []ExpectedFilter { expectedFilters := make([]ExpectedFilter, 0) for _, emitter := range logEmitters { for _, event := range cfg.General.EventsToEmit { @@ -230,11 +233,11 @@ func getStringSlice(length int) []string { } // emitEvents emits events from the provided log emitter concurrently according to the provided config -func emitEvents(ctx context.Context, l zerolog.Logger, logEmitter *contracts.LogEmitter, cfg *Config, wg *sync.WaitGroup, results chan LogEmitterChannel) { +func emitEvents(ctx context.Context, l zerolog.Logger, logEmitter *contracts.LogEmitter, cfg *lp_config.Config, wg *sync.WaitGroup, results chan LogEmitterChannel) { address := (*logEmitter).Address().String() localCounter := 0 defer wg.Done() - for i := 0; i < cfg.LoopedConfig.ExecutionCount; i++ { + for i := 0; i < *cfg.LoopedConfig.ExecutionCount; i++ { for _, event := range cfg.General.EventsToEmit { select { case <-ctx.Done(): @@ -245,13 +248,13 @@ func emitEvents(ctx context.Context, l zerolog.Logger, logEmitter *contracts.Log var err error switch event.Name { case "Log1": - _, err = (*logEmitter).EmitLogInts(getIntSlice(cfg.General.EventsPerTx)) + _, err = (*logEmitter).EmitLogInts(getIntSlice(*cfg.General.EventsPerTx)) case "Log2": - _, err = (*logEmitter).EmitLogIntsIndexed(getIntSlice(cfg.General.EventsPerTx)) + _, err = (*logEmitter).EmitLogIntsIndexed(getIntSlice(*cfg.General.EventsPerTx)) case "Log3": - _, err = (*logEmitter).EmitLogStrings(getStringSlice(cfg.General.EventsPerTx)) + _, err = (*logEmitter).EmitLogStrings(getStringSlice(*cfg.General.EventsPerTx)) case "Log4": - _, err = (*logEmitter).EmitLogIntMultiIndexed(1, 1, cfg.General.EventsPerTx) + _, err = (*logEmitter).EmitLogIntMultiIndexed(1, 1, *cfg.General.EventsPerTx) default: err = fmt.Errorf("unknown event name: %s", event.Name) } @@ -262,13 +265,13 @@ func emitEvents(ctx context.Context, l zerolog.Logger, logEmitter *contracts.Log } return } - localCounter += cfg.General.EventsPerTx + localCounter += *cfg.General.EventsPerTx - randomWait(cfg.LoopedConfig.FuzzConfig.MinEmitWaitTimeMs, cfg.LoopedConfig.FuzzConfig.MaxEmitWaitTimeMs) + randomWait(*cfg.LoopedConfig.MinEmitWaitTimeMs, *cfg.LoopedConfig.MaxEmitWaitTimeMs) } if (i+1)%10 == 0 { - l.Info().Str("Emitter address", address).Str("Index", fmt.Sprintf("%d/%d", i+1, cfg.LoopedConfig.ExecutionCount)).Msg("Emitted all three events") + l.Info().Str("Emitter address", address).Str("Index", fmt.Sprintf("%d/%d", i+1, *cfg.LoopedConfig.ExecutionCount)).Msg("Emitted all three events") } } } @@ -496,7 +499,7 @@ func (m *MissingLogs) IsEmpty() bool { } // GetMissingLogs returns a map of CL node name to missing logs in that node compared to EVM node to which the provided evm client is connected -func GetMissingLogs(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, evmClient blockchain.EVMClient, clnodeCluster *test_env.ClCluster, l zerolog.Logger, coreLogger core_logger.SugaredLogger, cfg *Config) (MissingLogs, error) { +func GetMissingLogs(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, evmClient blockchain.EVMClient, clnodeCluster *test_env.ClCluster, l zerolog.Logger, coreLogger core_logger.SugaredLogger, cfg *lp_config.Config) (MissingLogs, error) { wg := &sync.WaitGroup{} type dbQueryResult struct { @@ -669,7 +672,7 @@ func GetMissingLogs(startBlock, endBlock int64, logEmitters []*contracts.LogEmit } // PrintMissingLogsInfo prints various useful information about the missing logs -func PrintMissingLogsInfo(missingLogs map[string][]geth_types.Log, l zerolog.Logger, cfg *Config) { +func PrintMissingLogsInfo(missingLogs map[string][]geth_types.Log, l zerolog.Logger, cfg *lp_config.Config) { var findHumanName = func(topic common.Hash) string { for _, event := range cfg.General.EventsToEmit { if event.ID == topic { @@ -720,7 +723,7 @@ func PrintMissingLogsInfo(missingLogs map[string][]geth_types.Log, l zerolog.Log // getEVMLogs returns a slice of all logs emitted by the provided log emitters in the provided block range, // which are present in the EVM node to which the provided evm client is connected -func getEVMLogs(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, evmClient blockchain.EVMClient, l zerolog.Logger, cfg *Config) ([]geth_types.Log, error) { +func getEVMLogs(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, evmClient blockchain.EVMClient, l zerolog.Logger, cfg *lp_config.Config) ([]geth_types.Log, error) { allLogsInEVMNode := make([]geth_types.Log, 0) for j := 0; j < len(logEmitters); j++ { address := (*logEmitters[j]).Address() @@ -751,8 +754,8 @@ func getEVMLogs(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, } // ExecuteGenerator executes the configured generator and returns the total number of logs emitted -func ExecuteGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmitter) (int, error) { - if cfg.General.Generator == GeneratorType_WASP { +func ExecuteGenerator(t *testing.T, cfg *lp_config.Config, logEmitters []*contracts.LogEmitter) (int, error) { + if *cfg.General.Generator == lp_config.GeneratorType_WASP { return runWaspGenerator(t, cfg, logEmitters) } @@ -760,14 +763,14 @@ func ExecuteGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmi } // runWaspGenerator runs the wasp generator and returns the total number of logs emitted -func runWaspGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmitter) (int, error) { +func runWaspGenerator(t *testing.T, cfg *lp_config.Config, logEmitters []*contracts.LogEmitter) (int, error) { l := logging.GetTestLogger(t) var RPSprime int64 // if LPS is set, we need to calculate based on countract count and events per transaction - if cfg.Wasp.Load.LPS > 0 { - RPSprime = cfg.Wasp.Load.LPS / int64(cfg.General.Contracts) / int64(cfg.General.EventsPerTx) / int64(len(cfg.General.EventsToEmit)) + if *cfg.Wasp.LPS > 0 { + RPSprime = *cfg.Wasp.LPS / int64(*cfg.General.Contracts) / int64(*cfg.General.EventsPerTx) / int64(len(cfg.General.EventsToEmit)) if RPSprime < 1 { return 0, fmt.Errorf("invalid load configuration, effective RPS would have been zero. Adjust LPS, contracts count, events per tx or events to emit") @@ -775,8 +778,8 @@ func runWaspGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmi } // if RPS is set simply split it between contracts - if cfg.Wasp.Load.RPS > 0 { - RPSprime = cfg.Wasp.Load.RPS / int64(cfg.General.Contracts) + if *cfg.Wasp.RPS > 0 { + RPSprime = *cfg.Wasp.RPS / int64(*cfg.General.Contracts) } counter := &Counter{ @@ -791,16 +794,16 @@ func runWaspGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmi T: t, LoadType: wasp.RPS, GenName: fmt.Sprintf("log_poller_gen_%s", (*logEmitter).Address().String()), - RateLimitUnitDuration: cfg.Wasp.Load.RateLimitUnitDuration.Duration(), - CallTimeout: cfg.Wasp.Load.CallTimeout.Duration(), + RateLimitUnitDuration: cfg.Wasp.RateLimitUnitDuration.Duration, + CallTimeout: cfg.Wasp.CallTimeout.Duration, Schedule: wasp.Plain( RPSprime, - cfg.Wasp.Load.Duration.Duration(), + cfg.Wasp.Duration.Duration, ), Gun: NewLogEmitterGun( logEmitter, cfg.General.EventsToEmit, - cfg.General.EventsPerTx, + *cfg.General.EventsPerTx, l, ), SharedData: counter, @@ -818,7 +821,7 @@ func runWaspGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmi } // runLoopedGenerator runs the looped generator and returns the total number of logs emitted -func runLoopedGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogEmitter) (int, error) { +func runLoopedGenerator(t *testing.T, cfg *lp_config.Config, logEmitters []*contracts.LogEmitter) (int, error) { l := logging.GetTestLogger(t) // Start emitting events in parallel, each contract is emitting events in a separate goroutine @@ -870,15 +873,15 @@ func runLoopedGenerator(t *testing.T, cfg *Config, logEmitters []*contracts.LogE } // GetExpectedLogCount returns the expected number of logs to be emitted based on the provided config -func GetExpectedLogCount(cfg *Config) int64 { - if cfg.General.Generator == GeneratorType_WASP { - if cfg.Wasp.Load.RPS != 0 { - return cfg.Wasp.Load.RPS * int64(cfg.Wasp.Load.Duration.Duration().Seconds()) * int64(cfg.General.EventsPerTx) +func GetExpectedLogCount(cfg *lp_config.Config) int64 { + if *cfg.General.Generator == lp_config.GeneratorType_WASP { + if *cfg.Wasp.RPS != 0 { + return *cfg.Wasp.RPS * int64(cfg.Wasp.Duration.Seconds()) * int64(*cfg.General.EventsPerTx) } - return cfg.Wasp.Load.LPS * int64(cfg.Wasp.Load.Duration.Duration().Seconds()) + return *cfg.Wasp.LPS * int64(cfg.Wasp.Duration.Duration.Seconds()) } - return int64(len(cfg.General.EventsToEmit) * cfg.LoopedConfig.ExecutionCount * cfg.General.Contracts * cfg.General.EventsPerTx) + return int64(len(cfg.General.EventsToEmit) * *cfg.LoopedConfig.ExecutionCount * *cfg.General.Contracts * *cfg.General.EventsPerTx) } type PauseData struct { @@ -939,20 +942,20 @@ type ChaosPauseData struct { } // ExecuteChaosExperiment executes the configured chaos experiment, which consist of pausing CL node or Postgres containers -func ExecuteChaosExperiment(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv, cfg *Config, errorCh chan error) { - if cfg.ChaosConfig == nil || cfg.ChaosConfig.ExperimentCount == 0 { +func ExecuteChaosExperiment(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv, cfg *lp_config.Config, errorCh chan error) { + if cfg.ChaosConfig == nil || *cfg.ChaosConfig.ExperimentCount == 0 { errorCh <- nil return } - chaosChan := make(chan ChaosPauseData, cfg.ChaosConfig.ExperimentCount) + chaosChan := make(chan ChaosPauseData, *cfg.ChaosConfig.ExperimentCount) wg := &sync.WaitGroup{} go func() { // if we wanted to have more than 1 container paused, we'd need to make sure we aren't trying to pause an already paused one guardChan := make(chan struct{}, 1) - for i := 0; i < cfg.ChaosConfig.ExperimentCount; i++ { + for i := 0; i < *cfg.ChaosConfig.ExperimentCount; i++ { i := i wg.Add(1) guardChan <- struct{}{} @@ -963,7 +966,7 @@ func ExecuteChaosExperiment(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv current := i + 1 l.Info().Str("Current/Total", fmt.Sprintf("%d/%d", current, cfg.ChaosConfig.ExperimentCount)).Msg("Done with experiment") }() - chaosChan <- chaosPauseSyncFn(l, testEnv, cfg.ChaosConfig.TargetComponent) + chaosChan <- chaosPauseSyncFn(l, testEnv, *cfg.ChaosConfig.TargetComponent) time.Sleep(10 * time.Second) }() } @@ -1015,8 +1018,8 @@ func GetFinalityDepth(chainId int64) (int64, error) { } // GetEndBlockToWaitFor returns the end block to wait for based on chain id and finality tag provided in config -func GetEndBlockToWaitFor(endBlock, chainId int64, cfg *Config) (int64, error) { - if cfg.General.UseFinalityTag { +func GetEndBlockToWaitFor(endBlock, chainId int64, cfg *lp_config.Config) (int64, error) { + if *cfg.General.UseFinalityTag { return endBlock + 1, nil } @@ -1076,6 +1079,7 @@ func SetupLogPollerTestDocker( upkeepsNeeded int, lpPollingInterval time.Duration, finalityTagEnabled bool, + testConfig *tc.TestConfig, ) ( blockchain.EVMClient, []*client.ChainlinkClient, @@ -1086,9 +1090,10 @@ func SetupLogPollerTestDocker( *test_env.CLClusterTestEnv, ) { l := logging.GetTestLogger(t) + // Add registry version to config registryConfig.RegistryVersion = registryVersion - network := networks.MustGetSelectedNetworksFromEnv()[0] + network := networks.MustGetSelectedNetworkConfig(testConfig.Network)[0] finalityDepth, err := GetFinalityDepth(network.ChainID) require.NoError(t, err, "Error getting finality depth") @@ -1137,6 +1142,7 @@ func SetupLogPollerTestDocker( require.NoError(t, err, "Error building ethereum network config") env, err = test_env.NewCLTestEnvBuilder(). + WithTestConfig(testConfig). WithTestInstance(t). WithPrivateEthereumNetwork(cfg). WithCLNodes(clNodesCount). @@ -1204,9 +1210,9 @@ func SetupLogPollerTestDocker( } // UploadLogEmitterContractsAndWaitForFinalisation uploads the configured number of log emitter contracts and waits for the upload blocks to be finalised -func UploadLogEmitterContractsAndWaitForFinalisation(l zerolog.Logger, t *testing.T, testEnv *test_env.CLClusterTestEnv, cfg *Config) []*contracts.LogEmitter { +func UploadLogEmitterContractsAndWaitForFinalisation(l zerolog.Logger, t *testing.T, testEnv *test_env.CLClusterTestEnv, cfg *lp_config.Config) []*contracts.LogEmitter { logEmitters := make([]*contracts.LogEmitter, 0) - for i := 0; i < cfg.General.Contracts; i++ { + for i := 0; i < *cfg.General.Contracts; i++ { logEmitter, err := testEnv.ContractDeployer.DeployLogEmitterContract() logEmitters = append(logEmitters, &logEmitter) require.NoError(t, err, "Error deploying log emitter contract") @@ -1265,7 +1271,7 @@ func AssertContractAddressUniquneness(logEmitters []*contracts.LogEmitter) error // RegisterFiltersAndAssertUniquness registers the configured log filters and asserts that the filters are unique // meaning that for each log emitter address and topic there is only one filter -func RegisterFiltersAndAssertUniquness(l zerolog.Logger, registry contracts.KeeperRegistry, upkeepIDs []*big.Int, logEmitters []*contracts.LogEmitter, cfg *Config, upKeepsNeeded int) error { +func RegisterFiltersAndAssertUniquness(l zerolog.Logger, registry contracts.KeeperRegistry, upkeepIDs []*big.Int, logEmitters []*contracts.LogEmitter, cfg *lp_config.Config, upKeepsNeeded int) error { uniqueFilters := make(map[string]bool) upkeepIdIndex := 0