From 678b160edd343c3ec295897d79557e71f7f4dfab Mon Sep 17 00:00:00 2001 From: Eguzki Astiz Lezaun Date: Fri, 29 Nov 2024 14:57:06 +0100 Subject: [PATCH] added failures integration tests removing tests on examples Signed-off-by: Eguzki Astiz Lezaun --- .github/workflows/e2e.yaml | 72 --- Cargo.lock | 2 +- examples/missing-cluster/Makefile | 27 - examples/missing-cluster/README.md | 113 ---- examples/missing-cluster/docker-compose.yaml | 56 -- examples/missing-cluster/envoy.yaml | 156 ----- examples/missing-cluster/limits.yaml | 7 - examples/parallel-requests/Makefile | 17 - examples/parallel-requests/README.md | 66 -- .../parallel-requests/docker-compose.yaml | 56 -- examples/parallel-requests/envoy.yaml | 117 ---- examples/parallel-requests/limits.yaml | 7 - .../run-parallel-requests.sh | 38 -- examples/unreachable-service/Makefile | 27 - examples/unreachable-service/README.md | 118 ---- .../unreachable-service/docker-compose.yaml | 56 -- examples/unreachable-service/envoy.yaml | 156 ----- examples/unreachable-service/limits.yaml | 7 - tests/auth.rs | 8 +- tests/failures.rs | 577 ++++++++++++++++++ tests/multi.rs | 10 +- tests/rate_limited.rs | 8 +- tests/remote_address.rs | 2 +- 23 files changed, 592 insertions(+), 1111 deletions(-) delete mode 100644 examples/missing-cluster/Makefile delete mode 100644 examples/missing-cluster/README.md delete mode 100644 examples/missing-cluster/docker-compose.yaml delete mode 100644 examples/missing-cluster/envoy.yaml delete mode 100644 examples/missing-cluster/limits.yaml delete mode 100644 examples/parallel-requests/Makefile delete mode 100644 examples/parallel-requests/README.md delete mode 100644 examples/parallel-requests/docker-compose.yaml delete mode 100644 examples/parallel-requests/envoy.yaml delete mode 100644 examples/parallel-requests/limits.yaml delete mode 100755 examples/parallel-requests/run-parallel-requests.sh delete mode 100644 examples/unreachable-service/Makefile delete mode 100644 examples/unreachable-service/README.md delete mode 100644 examples/unreachable-service/docker-compose.yaml delete mode 100644 examples/unreachable-service/envoy.yaml delete mode 100644 examples/unreachable-service/limits.yaml create mode 100644 tests/failures.rs diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 00b8cd37..5aa07687 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -57,75 +57,3 @@ jobs: - name: Execute tests in the running services run: | make -f ./e2e/remote-address/Makefile test - missing-cluster: - name: Missing cluster integration test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - target: wasm32-unknown-unknown - - uses: arduino/setup-protoc@v1 - with: - version: '3.x' - - uses: actions-rs/cargo@v1 - with: - command: build - args: --target wasm32-unknown-unknown - - name: Run docker compose - run: | - docker compose -f ./e2e/missing-cluster/docker-compose.yaml run start_services - - name: Execute tests in the running services - run: | - make -f ./e2e/missing-cluster/Makefile test - parallel-requests: - name: Parallel requests integration test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - target: wasm32-unknown-unknown - - uses: arduino/setup-protoc@v1 - with: - version: '3.x' - - uses: actions-rs/cargo@v1 - with: - command: build - args: --target wasm32-unknown-unknown - - name: Run docker compose - run: | - docker compose -f ./e2e/parallel-requests/docker-compose.yaml run start_services - - name: Execute tests in the running services - run: | - make -f ./e2e/parallel-requests/Makefile test - unreachable-service: - name: Unreachable service integration test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - target: wasm32-unknown-unknown - - uses: arduino/setup-protoc@v1 - with: - version: '3.x' - - uses: actions-rs/cargo@v1 - with: - command: build - args: --target wasm32-unknown-unknown - - name: Run docker compose - run: | - docker compose -f ./e2e/unreachable-service/docker-compose.yaml run start_services - - name: Execute tests in the running services - run: | - make -f ./e2e/unreachable-service/Makefile test diff --git a/Cargo.lock b/Cargo.lock index 4cf1694e..474f52f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1314,7 +1314,7 @@ dependencies = [ [[package]] name = "proxy-wasm-test-framework" version = "0.1.0" -source = "git+https://github.com/Kuadrant/wasm-test-framework.git?branch=kuadrant#1bdc4d204d203342ff3d6d9b11b6ba69ee89465f" +source = "git+https://github.com/Kuadrant/wasm-test-framework.git?branch=kuadrant#bbc8079ee2cd078afaec6a0c077244ac7ad22d0a" dependencies = [ "anyhow", "lazy_static", diff --git a/examples/missing-cluster/Makefile b/examples/missing-cluster/Makefile deleted file mode 100644 index 8f8c354d..00000000 --- a/examples/missing-cluster/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -SHELL = /usr/bin/env bash -o pipefail -.SHELLFLAGS = -ec -.DEFAULT_GOAL := gateway -MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) -WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) -DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") - -run: - $(DOCKER) compose -f docker-compose.yaml run start_services - -test: - @{ \ - set -e ;\ - STATUSCODE=$(shell curl --silent --output /dev/null --write-out "%{http_code}" --max-time 5 --resolve fail-on-first-action.example.com:18000:127.0.0.1 http://fail-on-first-action.example.com:18000) && \ - echo "received status code $${STATUSCODE}" && \ - test $${STATUSCODE} -ne 200 ;\ - } - @{ \ - set -e ;\ - STATUSCODE=$(shell curl --silent --output /dev/null --write-out "%{http_code}" --max-time 5 --resolve fail-on-second-action.example.com:18000:127.0.0.1 http://fail-on-second-action.example.com:18000) && \ - echo "received status code $${STATUSCODE}" && \ - test $${STATUSCODE} -ne 200 ;\ - } - -clean: - $(DOCKER) compose down --volumes --remove-orphans - $(DOCKER) compose -f docker-compose.yaml down --volumes --remove-orphans diff --git a/examples/missing-cluster/README.md b/examples/missing-cluster/README.md deleted file mode 100644 index 39d74e30..00000000 --- a/examples/missing-cluster/README.md +++ /dev/null @@ -1,113 +0,0 @@ -## Missing cluster integration test - -This is a integration test to validate when envoy cluster does not exist. - -The test configures not existing envoy cluster on the fist action `fail-on-first-action.example.com`, -as well as on the second action `fail-on-second-action.example.com`. Reason being to validate -error handling on the `on_grpc_call_response` event. - -This test is being added to the CI test suite - -### Description - -```json -"services": { - "existing-service": { - "type": "ratelimit", - "endpoint": "existing-cluster", - "failureMode": "deny" - } - "mistyped-service": { - "type": "ratelimit", - "endpoint": "does-not-exist", - "failureMode": "deny" - } -}, -"actionSets": [ -{ - "name": "envoy-cluster-not-found-on-first-action", - "routeRuleConditions": { - "hostnames": [ - "fail-on-first-action.example.com" - ] - }, - "actions": [ - { - "service": "mistyped-service", - "scope": "b", - "data": [ - { - "expression": { - "key": "limit_to_be_activated", - "value": "1" - } - } - ] - } - ] -}, -{ - "name": "envoy-cluster-not-found-on-second-action", - "routeRuleConditions": { - "hostnames": [ - "fail-on-second-action.example.com" - ] - }, - "actions": [ - { - "service": "existing-service", - "scope": "b", - "data": [ - { - "expression": { - "key": "limit_to_be_activated", - "value": "1" - } - } - ] - }, - { - "service": "mistyped-service", - "scope": "b", - "data": [ - { - "expression": { - "key": "limit_to_be_activated", - "value": "1" - } - } - ] - } - ] -} -] -``` - -Check Envoy logs: - -``` -docker compose logs -f envoy -``` - -The test will run two requests and expect them to fail because `failureMode` is set to `deny`. - -### Run Manually - -It requires Wasm module being built at `target/wasm32-unknown-unknown/debug/wasm_shim.wasm`. -Check *Makefile* at the root of the project to build the module. - -``` -make run -``` - -Run the test - -``` -make test -``` - -### Clean up - -``` -make clean -``` diff --git a/examples/missing-cluster/docker-compose.yaml b/examples/missing-cluster/docker-compose.yaml deleted file mode 100644 index bcecea74..00000000 --- a/examples/missing-cluster/docker-compose.yaml +++ /dev/null @@ -1,56 +0,0 @@ ---- -services: - envoy: - image: envoyproxy/envoy:v1.31-latest - depends_on: - - limitador - - upstream - command: - - /usr/local/bin/envoy - - --config-path - - /etc/envoy.yaml - - --log-level - - info - - --component-log-level - - wasm:debug,http:debug,router:debug - - --service-cluster - - proxy - expose: - - "80" - - "8001" - ports: - - "18000:80" - - "18001:8001" - volumes: - - ./envoy.yaml:/etc/envoy.yaml - - ../../target/wasm32-unknown-unknown/debug/wasm_shim.wasm:/opt/kuadrant/wasm/wasm_shim.wasm - limitador: - image: quay.io/kuadrant/limitador:latest - command: ["limitador-server", "-vvv", "/opt/kuadrant/limits/limits.yaml"] - ports: - - "18080:8080" - - "18081:8081" - expose: - - "8080" - - "8081" - volumes: - - ./limits.yaml:/opt/kuadrant/limits/limits.yaml - upstream: - image: quay.io/kuadrant/authorino-examples:talker-api - environment: - PORT: 3000 - expose: - - "3000" - start_services: - image: alpine - depends_on: - - envoy - command: > - /bin/sh -c " - while ! nc -z envoy 80; - do - echo sleeping; - sleep 1; - done; - echo Connected! - " diff --git a/examples/missing-cluster/envoy.yaml b/examples/missing-cluster/envoy.yaml deleted file mode 100644 index 16929772..00000000 --- a/examples/missing-cluster/envoy.yaml +++ /dev/null @@ -1,156 +0,0 @@ ---- -static_resources: - listeners: - - name: main - address: - socket_address: - address: 0.0.0.0 - port_value: 80 - filter_chains: - - filters: - - name: envoy.filters.network.http_connection_manager - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - stat_prefix: ingress_http - use_remote_address: true - xff_num_trusted_hops: 1 - route_config: - name: local_route - virtual_hosts: - - name: local_service - domains: - - "*" - routes: - - match: - prefix: "/" - route: - cluster: upstream - http_filters: - - name: envoy.filters.http.wasm - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm - config: - name: kuadrant_wasm - root_id: kuadrant_wasm - vm_config: - vm_id: vm.sentinel.kuadrant_wasm - runtime: envoy.wasm.runtime.v8 - code: - local: - filename: /opt/kuadrant/wasm/wasm_shim.wasm - allow_precompiled: true - configuration: - "@type": "type.googleapis.com/google.protobuf.StringValue" - value: > - { - "services": { - "limitador": { - "type": "ratelimit", - "endpoint": "limitador", - "failureMode": "deny" - }, - "mistyped-service": { - "type": "ratelimit", - "endpoint": "mistyped-service", - "failureMode": "deny" - } - }, - "actionSets": [ - { - "name": "envoy-cluster-not-found-on-first-action", - "routeRuleConditions": { - "hostnames": [ - "fail-on-first-action.example.com" - ] - }, - "actions": [ - { - "service": "mistyped-service", - "scope": "a", - "data": [ - { - "expression": { - "key": "limit_to_be_activated", - "value": "1" - } - } - ] - } - ] - }, - { - "name": "envoy-cluster-not-found-on-second-action", - "routeRuleConditions": { - "hostnames": [ - "fail-on-second-action.example.com" - ] - }, - "actions": [ - { - "service": "limitador", - "scope": "a", - "data": [ - { - "expression": { - "key": "limit_to_be_activated", - "value": "1" - } - } - ] - }, - { - "service": "mistyped-service", - "scope": "a", - "data": [ - { - "expression": { - "key": "limit_to_be_activated", - "value": "1" - } - } - ] - } - ] - } - ] - } - - name: envoy.filters.http.router - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - clusters: - - name: upstream - connect_timeout: 0.25s - type: STRICT_DNS - lb_policy: round_robin - load_assignment: - cluster_name: upstream - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: upstream - port_value: 3000 - - name: limitador - connect_timeout: 0.25s - type: STRICT_DNS - lb_policy: round_robin - typed_extension_protocol_options: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicit_http_config: - http2_protocol_options: {} - load_assignment: - cluster_name: limitador - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: limitador - port_value: 8081 -admin: - address: - socket_address: - address: 0.0.0.0 - port_value: 8001 diff --git a/examples/missing-cluster/limits.yaml b/examples/missing-cluster/limits.yaml deleted file mode 100644 index 0c53707a..00000000 --- a/examples/missing-cluster/limits.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- namespace: ratelimit-source - max_value: 30 - seconds: 60 - conditions: - - "limit_to_be_activated == '1'" - variables: [] diff --git a/examples/parallel-requests/Makefile b/examples/parallel-requests/Makefile deleted file mode 100644 index c3a8b8f6..00000000 --- a/examples/parallel-requests/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -SHELL = /usr/bin/env bash -o pipefail -.SHELLFLAGS = -ec -.DEFAULT_GOAL := gateway -MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) -WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) -DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") - -run: - $(DOCKER) compose -f docker-compose.yaml run start_services - -test: - $(WORKDIR)/run-parallel-requests.sh - - -clean: - $(DOCKER) compose down --volumes --remove-orphans - $(DOCKER) compose -f docker-compose.yaml down --volumes --remove-orphans diff --git a/examples/parallel-requests/README.md b/examples/parallel-requests/README.md deleted file mode 100644 index 9535087a..00000000 --- a/examples/parallel-requests/README.md +++ /dev/null @@ -1,66 +0,0 @@ -## Parallel requests integration test - -This is a integration test to validate when envoy receives multiple parallel requests. - -This test is being added to the CI test suite - -### Description - -The Wasm configuration defines a set of rules for `*.example.com` - -```json -"services": { - "limitador": { - "type": "ratelimit", - "endpoint": "limitador", - "failureMode": "deny" - } -}, -"actionSets": [ -{ - "actions": [ - { - "service": "limitador", - "scope": "b", - "data": [ - { - "expression": { - "key": "limit_to_be_activated", - "value": "1" - } - } - ] - } - ] -} -] -``` - -Check Envoy logs: - -``` -docker compose logs -f envoy -``` - -The test will run multiple requests in parallel and expect all of them to succeed. - -### Run Manually - -It requires Wasm module being built at `target/wasm32-unknown-unknown/debug/wasm_shim.wasm`. -Check *Makefile* at the root of the project to build the module. - -``` -make run -``` - -Run the test - -``` -make test -``` - -### Clean up - -``` -make clean -``` diff --git a/examples/parallel-requests/docker-compose.yaml b/examples/parallel-requests/docker-compose.yaml deleted file mode 100644 index bcecea74..00000000 --- a/examples/parallel-requests/docker-compose.yaml +++ /dev/null @@ -1,56 +0,0 @@ ---- -services: - envoy: - image: envoyproxy/envoy:v1.31-latest - depends_on: - - limitador - - upstream - command: - - /usr/local/bin/envoy - - --config-path - - /etc/envoy.yaml - - --log-level - - info - - --component-log-level - - wasm:debug,http:debug,router:debug - - --service-cluster - - proxy - expose: - - "80" - - "8001" - ports: - - "18000:80" - - "18001:8001" - volumes: - - ./envoy.yaml:/etc/envoy.yaml - - ../../target/wasm32-unknown-unknown/debug/wasm_shim.wasm:/opt/kuadrant/wasm/wasm_shim.wasm - limitador: - image: quay.io/kuadrant/limitador:latest - command: ["limitador-server", "-vvv", "/opt/kuadrant/limits/limits.yaml"] - ports: - - "18080:8080" - - "18081:8081" - expose: - - "8080" - - "8081" - volumes: - - ./limits.yaml:/opt/kuadrant/limits/limits.yaml - upstream: - image: quay.io/kuadrant/authorino-examples:talker-api - environment: - PORT: 3000 - expose: - - "3000" - start_services: - image: alpine - depends_on: - - envoy - command: > - /bin/sh -c " - while ! nc -z envoy 80; - do - echo sleeping; - sleep 1; - done; - echo Connected! - " diff --git a/examples/parallel-requests/envoy.yaml b/examples/parallel-requests/envoy.yaml deleted file mode 100644 index 94d7a942..00000000 --- a/examples/parallel-requests/envoy.yaml +++ /dev/null @@ -1,117 +0,0 @@ ---- -static_resources: - listeners: - - name: main - address: - socket_address: - address: 0.0.0.0 - port_value: 80 - filter_chains: - - filters: - - name: envoy.filters.network.http_connection_manager - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - stat_prefix: ingress_http - use_remote_address: true - xff_num_trusted_hops: 1 - route_config: - name: local_route - virtual_hosts: - - name: local_service - domains: - - "*" - routes: - - match: - prefix: "/" - route: - cluster: upstream - http_filters: - - name: envoy.filters.http.wasm - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm - config: - name: kuadrant_wasm - root_id: kuadrant_wasm - vm_config: - vm_id: vm.sentinel.kuadrant_wasm - runtime: envoy.wasm.runtime.v8 - code: - local: - filename: /opt/kuadrant/wasm/wasm_shim.wasm - allow_precompiled: true - configuration: - "@type": "type.googleapis.com/google.protobuf.StringValue" - value: > - { - "services": { - "limitador": { - "type": "ratelimit", - "endpoint": "limitador", - "failureMode": "deny" - } - }, - "actionSets": [ - { - "name": "example action set", - "routeRuleConditions": { - "hostnames": [ - "*.example.com" - ] - }, - "actions": [ - { - "service": "limitador", - "scope": "a", - "data": [ - { - "expression": { - "key": "limit_to_be_activated", - "value": "1" - } - } - ] - } - ] - } - ] - } - - name: envoy.filters.http.router - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - clusters: - - name: upstream - connect_timeout: 0.25s - type: STRICT_DNS - lb_policy: round_robin - load_assignment: - cluster_name: upstream - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: upstream - port_value: 3000 - - name: limitador - connect_timeout: 0.25s - type: STRICT_DNS - lb_policy: round_robin - typed_extension_protocol_options: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicit_http_config: - http2_protocol_options: {} - load_assignment: - cluster_name: limitador - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: limitador - port_value: 8081 -admin: - address: - socket_address: - address: 0.0.0.0 - port_value: 8001 diff --git a/examples/parallel-requests/limits.yaml b/examples/parallel-requests/limits.yaml deleted file mode 100644 index 0c53707a..00000000 --- a/examples/parallel-requests/limits.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- namespace: ratelimit-source - max_value: 30 - seconds: 60 - conditions: - - "limit_to_be_activated == '1'" - variables: [] diff --git a/examples/parallel-requests/run-parallel-requests.sh b/examples/parallel-requests/run-parallel-requests.sh deleted file mode 100755 index 0f7cde6f..00000000 --- a/examples/parallel-requests/run-parallel-requests.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -if ! command -v curl &>/dev/null -then - echo "curl not found..." >&2 - exit 1 -fi - -curl --silent --output /dev/null --fail --max-time 5 --resolve test.example.com:18000:127.0.0.1 http://test.example.com:18000 & REQ1=$! -curl --silent --output /dev/null --fail --max-time 5 --resolve test.example.com:18000:127.0.0.1 http://test.example.com:18000 & REQ2=$! -curl --silent --output /dev/null --fail --max-time 5 --resolve test.example.com:18000:127.0.0.1 http://test.example.com:18000 & REQ3=$! - -wait $REQ1 -RET_REQ1=$? -echo "REQ1 returned $RET_REQ1" -if test "$RET_REQ1" != "0"; then - echo "REQ1 exited with abnormal status" - exit 1; -fi - -wait $REQ2 -RET_REQ2=$? -echo "REQ2 returned $RET_REQ2" -if test "$RET_REQ2" != "0"; then - echo "REQ2 exited with abnormal status" - exit 1; -fi - -wait $REQ3 -RET_REQ3=$? -echo "REQ3 returned $RET_REQ3" -if test "$RET_REQ3" != "0"; then - echo "REQ3 exited with abnormal status" - exit 1; -fi - -echo "All requests succeeded" -exit 0 diff --git a/examples/unreachable-service/Makefile b/examples/unreachable-service/Makefile deleted file mode 100644 index 8f8c354d..00000000 --- a/examples/unreachable-service/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -SHELL = /usr/bin/env bash -o pipefail -.SHELLFLAGS = -ec -.DEFAULT_GOAL := gateway -MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) -WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) -DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") - -run: - $(DOCKER) compose -f docker-compose.yaml run start_services - -test: - @{ \ - set -e ;\ - STATUSCODE=$(shell curl --silent --output /dev/null --write-out "%{http_code}" --max-time 5 --resolve fail-on-first-action.example.com:18000:127.0.0.1 http://fail-on-first-action.example.com:18000) && \ - echo "received status code $${STATUSCODE}" && \ - test $${STATUSCODE} -ne 200 ;\ - } - @{ \ - set -e ;\ - STATUSCODE=$(shell curl --silent --output /dev/null --write-out "%{http_code}" --max-time 5 --resolve fail-on-second-action.example.com:18000:127.0.0.1 http://fail-on-second-action.example.com:18000) && \ - echo "received status code $${STATUSCODE}" && \ - test $${STATUSCODE} -ne 200 ;\ - } - -clean: - $(DOCKER) compose down --volumes --remove-orphans - $(DOCKER) compose -f docker-compose.yaml down --volumes --remove-orphans diff --git a/examples/unreachable-service/README.md b/examples/unreachable-service/README.md deleted file mode 100644 index 54568257..00000000 --- a/examples/unreachable-service/README.md +++ /dev/null @@ -1,118 +0,0 @@ -## Basic integration test - -This is a integration test to validate when envoy cluster exists but it is not reachable. - -The test configures unreachable envoy cluster on the fist action `fail-on-first-action.example.com`, -as well as on the second action `fail-on-second-action.example.com`. Reason being to validate -error handling on the `on_grpc_call_response` event. - -This test is being added to the CI test suite - -### Description - -```yaml -"services": { - "limitadorA": { - "type": "ratelimit", - "endpoint": "limitador", - "failureMode": "deny" - }, - "limitador-unreachable": { - "type": "ratelimit", - "endpoint": "unreachable-cluster", - "failureMode": "deny" - } -}, -"actionSets": [ -{ - "name": "envoy-cluster-unreachable-on-first-action", - "routeRuleConditions": { - "hostnames": [ - "fail-on-first-action.example.com" - ] - }, - "actions": [ - { - "service": "limitador-unreachable", - "scope": "a", - "data": [ - { - "expression": { - "key": "a", - "value": "1" - } - } - ] - } - ] -}, -{ - "name": "envoy-cluster-unreachable-on-second-action", - "routeRuleConditions": { - "hostnames": [ - "fail-on-second-action.example.com" - ] - }, - "actions": [ - { - "service": "limitadorA", - "scope": "b", - "data": [ - { - "expression": { - "key": "limit_to_be_activated", - "value": "1" - } - } - ] - }, - { - "service": "limitador-unreachable", - "scope": "b", - "data": [ - { - "expression": { - "key": "limit_to_be_activated", - "value": "1" - } - } - ] - } - ] -} -] -``` - -And a new limit configuration - -```yaml -- namespace: basic - max_value: 30 - seconds: 60 - conditions: - - "a == '1'" - variables: [] -``` - -The test will run two requests and expect them to fail because `failureMode` is set to `deny`. - -### Run Manually - -It requires Wasm module being built at `target/wasm32-unknown-unknown/debug/wasm_shim.wasm`. -Check *Makefile* at the root of the project to build the module. - -``` -make run -``` - -Run the test - -``` -make test -``` - -### Clean up - -``` -make clean -``` diff --git a/examples/unreachable-service/docker-compose.yaml b/examples/unreachable-service/docker-compose.yaml deleted file mode 100644 index bcecea74..00000000 --- a/examples/unreachable-service/docker-compose.yaml +++ /dev/null @@ -1,56 +0,0 @@ ---- -services: - envoy: - image: envoyproxy/envoy:v1.31-latest - depends_on: - - limitador - - upstream - command: - - /usr/local/bin/envoy - - --config-path - - /etc/envoy.yaml - - --log-level - - info - - --component-log-level - - wasm:debug,http:debug,router:debug - - --service-cluster - - proxy - expose: - - "80" - - "8001" - ports: - - "18000:80" - - "18001:8001" - volumes: - - ./envoy.yaml:/etc/envoy.yaml - - ../../target/wasm32-unknown-unknown/debug/wasm_shim.wasm:/opt/kuadrant/wasm/wasm_shim.wasm - limitador: - image: quay.io/kuadrant/limitador:latest - command: ["limitador-server", "-vvv", "/opt/kuadrant/limits/limits.yaml"] - ports: - - "18080:8080" - - "18081:8081" - expose: - - "8080" - - "8081" - volumes: - - ./limits.yaml:/opt/kuadrant/limits/limits.yaml - upstream: - image: quay.io/kuadrant/authorino-examples:talker-api - environment: - PORT: 3000 - expose: - - "3000" - start_services: - image: alpine - depends_on: - - envoy - command: > - /bin/sh -c " - while ! nc -z envoy 80; - do - echo sleeping; - sleep 1; - done; - echo Connected! - " diff --git a/examples/unreachable-service/envoy.yaml b/examples/unreachable-service/envoy.yaml deleted file mode 100644 index 9b8b0261..00000000 --- a/examples/unreachable-service/envoy.yaml +++ /dev/null @@ -1,156 +0,0 @@ ---- -static_resources: - listeners: - - name: main - address: - socket_address: - address: 0.0.0.0 - port_value: 80 - filter_chains: - - filters: - - name: envoy.filters.network.http_connection_manager - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - stat_prefix: ingress_http - use_remote_address: true - xff_num_trusted_hops: 1 - route_config: - name: local_route - virtual_hosts: - - name: local_service - domains: - - "*" - routes: - - match: - prefix: "/" - route: - cluster: upstream - http_filters: - - name: envoy.filters.http.wasm - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm - config: - name: kuadrant_wasm - root_id: kuadrant_wasm - vm_config: - vm_id: vm.sentinel.kuadrant_wasm - runtime: envoy.wasm.runtime.v8 - code: - local: - filename: /opt/kuadrant/wasm/wasm_shim.wasm - allow_precompiled: true - configuration: - "@type": "type.googleapis.com/google.protobuf.StringValue" - value: > - { - "services": { - "limitador": { - "type": "ratelimit", - "endpoint": "limitador", - "failureMode": "deny" - }, - "limitador-unreachable": { - "type": "ratelimit", - "endpoint": "unreachable-cluster", - "failureMode": "deny" - } - }, - "actionSets": [ - { - "name": "envoy-cluster-unreachable-on-first-action", - "routeRuleConditions": { - "hostnames": [ - "fail-on-first-action.example.com" - ] - }, - "actions": [ - { - "service": "limitador-unreachable", - "scope": "a", - "data": [ - { - "expression": { - "key": "a", - "value": "1" - } - } - ] - } - ] - }, - { - "name": "envoy-cluster-unreachable-on-second-action", - "routeRuleConditions": { - "hostnames": [ - "fail-on-second-action.example.com" - ] - }, - "actions": [ - { - "service": "limitador", - "scope": "a", - "data": [ - { - "expression": { - "key": "a", - "value": "1" - } - } - ] - }, - { - "service": "limitador-unreachable", - "scope": "a", - "data": [ - { - "expression": { - "key": "a", - "value": "1" - } - } - ] - } - ] - } - ] - } - - name: envoy.filters.http.router - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - clusters: - - name: upstream - connect_timeout: 0.25s - type: STRICT_DNS - lb_policy: round_robin - load_assignment: - cluster_name: upstream - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: upstream - port_value: 3000 - - name: limitador - connect_timeout: 0.25s - type: STRICT_DNS - lb_policy: round_robin - typed_extension_protocol_options: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicit_http_config: - http2_protocol_options: {} - load_assignment: - cluster_name: limitador - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: limitador - port_value: 8081 -admin: - address: - socket_address: - address: 0.0.0.0 - port_value: 8001 diff --git a/examples/unreachable-service/limits.yaml b/examples/unreachable-service/limits.yaml deleted file mode 100644 index 3d75521e..00000000 --- a/examples/unreachable-service/limits.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- namespace: a - max_value: 30 - seconds: 60 - conditions: - - "a == '1'" - variables: [] diff --git a/tests/auth.rs b/tests/auth.rs index d0ded736..953b9066 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -193,7 +193,7 @@ fn it_auths() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"), @@ -390,7 +390,7 @@ fn it_denies() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"), @@ -605,7 +605,7 @@ fn it_does_not_fold_auth_actions() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"), @@ -717,7 +717,7 @@ fn it_does_not_fold_auth_actions() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .execute_and_expect(ReturnType::None) .unwrap(); diff --git a/tests/failures.rs b/tests/failures.rs new file mode 100644 index 00000000..298fde95 --- /dev/null +++ b/tests/failures.rs @@ -0,0 +1,577 @@ +use crate::util::common::wasm_module; +use proxy_wasm_test_framework::tester; +use proxy_wasm_test_framework::types::Status as TestStatus; +use proxy_wasm_test_framework::types::{Action, BufferType, LogLevel, MapType, ReturnType}; +use serial_test::serial; + +pub mod util; + +#[test] +#[serial] +fn it_fails_on_first_action_grpc_call() { + // this usually happens when target service is not registered on host + let args = tester::MockSettings { + wasm_path: wasm_module(), + quiet: false, + allow_unexpected: false, + }; + let mut module = tester::mock(args).unwrap(); + + module + .call_start() + .execute_and_expect(ReturnType::None) + .unwrap(); + + let root_context = 1; + let cfg = r#"{ + "services": { + "mistyped-service": { + "type": "ratelimit", + "endpoint": "does-not-exist", + "failureMode": "deny", + "timeout": "5s" + } + }, + "actionSets": [ + { + "name": "some-name", + "routeRuleConditions": { + "hostnames": ["example.com"] + }, + "actions": [ + { + "service": "mistyped-service", + "scope": "a", + "data": [ + { + "expression": { + "key": "limit_to_be_activated", + "value": "1" + } + } + ] + }] + }] + }"#; + + module + .call_proxy_on_context_create(root_context, 0) + .expect_log(Some(LogLevel::Info), Some("#1 set_root_context")) + .execute_and_expect(ReturnType::None) + .unwrap(); + module + .call_proxy_on_configure(root_context, 0) + .expect_log(Some(LogLevel::Info), Some("#1 on_configure")) + .expect_get_buffer_bytes(Some(BufferType::PluginConfiguration)) + .returning(Some(cfg.as_bytes())) + .expect_log(Some(LogLevel::Info), None) + .execute_and_expect(ReturnType::Bool(true)) + .unwrap(); + + let http_context = 2; + module + .call_proxy_on_context_create(http_context, root_context) + .expect_log(Some(LogLevel::Debug), Some("#2 create_http_context")) + .execute_and_expect(ReturnType::None) + .unwrap(); + + module + .call_proxy_on_request_headers(http_context, 0, false) + .expect_log(Some(LogLevel::Debug), Some("#2 on_http_request_headers")) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some(":authority")) + .returning(Some("example.com")) + .expect_log( + Some(LogLevel::Debug), + Some("#2 action_set selected some-name"), + ) + // retrieving tracing headers + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("traceparent")) + .returning(None) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("tracestate")) + .returning(None) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("baggage")) + .returning(None) + .expect_grpc_call( + Some("does-not-exist"), + Some("envoy.service.ratelimit.v3.RateLimitService"), + Some("ShouldRateLimit"), + Some(&[0, 0, 0, 0]), + Some(&[ + 10, 1, 97, 18, 28, 10, 26, 10, 21, 108, 105, 109, 105, 116, 95, 116, 111, 95, 98, + 101, 95, 97, 99, 116, 105, 118, 97, 116, 101, 100, 18, 1, 49, 24, 1, + ]), + Some(5000), + ) + .returning(Err(TestStatus::ParseFailure)) + .expect_log( + Some(LogLevel::Error), + Some("OperationError { status: ParseFailure, failure_mode: Deny }"), + ) + .expect_log( + Some(LogLevel::Warn), + Some("OperationError Status: ParseFailure"), + ) + .expect_send_local_response( + Some(500), + Some("Internal Server Error.\n"), + Some(vec![]), + Some(-1), + ) + .execute_and_expect(ReturnType::Action(Action::Continue)) + .unwrap(); +} + +#[test] +#[serial] +fn it_fails_on_second_action_grpc_call() { + // this usually happens when target service is not registered on host + // testing error handling on the second call as the error handling is implemented + // differently from the first call + let args = tester::MockSettings { + wasm_path: wasm_module(), + quiet: false, + allow_unexpected: false, + }; + let mut module = tester::mock(args).unwrap(); + + module + .call_start() + .execute_and_expect(ReturnType::None) + .unwrap(); + + let root_context = 1; + let cfg = r#"{ + "services": { + "limitador": { + "type": "ratelimit", + "endpoint": "limitador-cluster", + "failureMode": "deny", + "timeout": "5s" + }, + "mistyped-service": { + "type": "ratelimit", + "endpoint": "does-not-exist", + "failureMode": "deny", + "timeout": "5s" + } + }, + "actionSets": [ + { + "name": "some-name", + "routeRuleConditions": { + "hostnames": ["example.com"] + }, + "actions": [ + { + "service": "limitador", + "scope": "a", + "data": [ + { + "expression": { + "key": "limit_to_be_activated", + "value": "1" + } + } + ] + }, + { + "service": "mistyped-service", + "scope": "a", + "data": [ + { + "expression": { + "key": "limit_to_be_activated", + "value": "1" + } + } + ] + }] + }] + }"#; + + module + .call_proxy_on_context_create(root_context, 0) + .expect_log(Some(LogLevel::Info), Some("#1 set_root_context")) + .execute_and_expect(ReturnType::None) + .unwrap(); + module + .call_proxy_on_configure(root_context, 0) + .expect_log(Some(LogLevel::Info), Some("#1 on_configure")) + .expect_get_buffer_bytes(Some(BufferType::PluginConfiguration)) + .returning(Some(cfg.as_bytes())) + .expect_log(Some(LogLevel::Info), None) + .execute_and_expect(ReturnType::Bool(true)) + .unwrap(); + + let http_context = 2; + module + .call_proxy_on_context_create(http_context, root_context) + .expect_log(Some(LogLevel::Debug), Some("#2 create_http_context")) + .execute_and_expect(ReturnType::None) + .unwrap(); + + module + .call_proxy_on_request_headers(http_context, 0, false) + .expect_log(Some(LogLevel::Debug), Some("#2 on_http_request_headers")) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some(":authority")) + .returning(Some("example.com")) + .expect_log( + Some(LogLevel::Debug), + Some("#2 action_set selected some-name"), + ) + // retrieving tracing headers + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("traceparent")) + .returning(None) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("tracestate")) + .returning(None) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("baggage")) + .returning(None) + .expect_grpc_call( + Some("limitador-cluster"), + Some("envoy.service.ratelimit.v3.RateLimitService"), + Some("ShouldRateLimit"), + Some(&[0, 0, 0, 0]), + Some(&[ + 10, 1, 97, 18, 28, 10, 26, 10, 21, 108, 105, 109, 105, 116, 95, 116, 111, 95, 98, + 101, 95, 97, 99, 116, 105, 118, 97, 116, 101, 100, 18, 1, 49, 24, 1, + ]), + Some(5000), + ) + .returning(Ok(42)) + .expect_log( + Some(LogLevel::Debug), + Some("#2 initiated gRPC call (id# 42)"), + ) + .execute_and_expect(ReturnType::Action(Action::Pause)) + .unwrap(); + + let grpc_response: [u8; 2] = [8, 1]; + module + .call_proxy_on_grpc_receive(http_context, 42, grpc_response.len() as i32) + .expect_log( + Some(LogLevel::Debug), + Some("#2 on_grpc_call_response: received gRPC call response: token: 42, status: 0"), + ) + .expect_get_buffer_bytes(Some(BufferType::GrpcReceiveBuffer)) + .returning(Some(&grpc_response)) + .expect_grpc_call( + Some("does-not-exist"), + Some("envoy.service.ratelimit.v3.RateLimitService"), + Some("ShouldRateLimit"), + Some(&[0, 0, 0, 0]), + Some(&[ + 10, 1, 97, 18, 28, 10, 26, 10, 21, 108, 105, 109, 105, 116, 95, 116, 111, 95, 98, + 101, 95, 97, 99, 116, 105, 118, 97, 116, 101, 100, 18, 1, 49, 24, 1, + ]), + Some(5000), + ) + .returning(Err(TestStatus::ParseFailure)) + .expect_log( + Some(LogLevel::Error), + Some("OperationError { status: ParseFailure, failure_mode: Deny }"), + ) + .expect_send_local_response( + Some(500), + Some("Internal Server Error.\n"), + Some(vec![]), + Some(-1), + ) + .execute_and_expect(ReturnType::None) + .unwrap(); +} + +#[test] +#[serial] +fn it_fails_on_first_action_grpc_response() { + // this usually happens when target service is registered on host but unreachable + let args = tester::MockSettings { + wasm_path: wasm_module(), + quiet: false, + allow_unexpected: false, + }; + let mut module = tester::mock(args).unwrap(); + + module + .call_start() + .execute_and_expect(ReturnType::None) + .unwrap(); + + let root_context = 1; + let cfg = r#"{ + "services": { + "limitador-unreachable": { + "type": "ratelimit", + "endpoint": "unreachable-cluster", + "failureMode": "deny", + "timeout": "5s" + } + }, + "actionSets": [ + { + "name": "some-name", + "routeRuleConditions": { + "hostnames": ["example.com"] + }, + "actions": [ + { + "service": "limitador-unreachable", + "scope": "a", + "data": [ + { + "expression": { + "key": "limit_to_be_activated", + "value": "1" + } + } + ] + }] + }] + }"#; + + module + .call_proxy_on_context_create(root_context, 0) + .expect_log(Some(LogLevel::Info), Some("#1 set_root_context")) + .execute_and_expect(ReturnType::None) + .unwrap(); + module + .call_proxy_on_configure(root_context, 0) + .expect_log(Some(LogLevel::Info), Some("#1 on_configure")) + .expect_get_buffer_bytes(Some(BufferType::PluginConfiguration)) + .returning(Some(cfg.as_bytes())) + .expect_log(Some(LogLevel::Info), None) + .execute_and_expect(ReturnType::Bool(true)) + .unwrap(); + + let http_context = 2; + module + .call_proxy_on_context_create(http_context, root_context) + .expect_log(Some(LogLevel::Debug), Some("#2 create_http_context")) + .execute_and_expect(ReturnType::None) + .unwrap(); + + module + .call_proxy_on_request_headers(http_context, 0, false) + .expect_log(Some(LogLevel::Debug), Some("#2 on_http_request_headers")) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some(":authority")) + .returning(Some("example.com")) + .expect_log( + Some(LogLevel::Debug), + Some("#2 action_set selected some-name"), + ) + // retrieving tracing headers + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("traceparent")) + .returning(None) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("tracestate")) + .returning(None) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("baggage")) + .returning(None) + .expect_grpc_call( + Some("unreachable-cluster"), + Some("envoy.service.ratelimit.v3.RateLimitService"), + Some("ShouldRateLimit"), + Some(&[0, 0, 0, 0]), + Some(&[ + 10, 1, 97, 18, 28, 10, 26, 10, 21, 108, 105, 109, 105, 116, 95, 116, 111, 95, 98, + 101, 95, 97, 99, 116, 105, 118, 97, 116, 101, 100, 18, 1, 49, 24, 1, + ]), + Some(5000), + ) + .returning(Ok(42)) + .expect_log( + Some(LogLevel::Debug), + Some("#2 initiated gRPC call (id# 42)"), + ) + .execute_and_expect(ReturnType::Action(Action::Pause)) + .unwrap(); + + let status_code = 14; + module + .proxy_on_grpc_close(http_context, 42, status_code) + .expect_log( + Some(LogLevel::Debug), + Some("#2 on_grpc_call_response: received gRPC call response: token: 42, status: 14"), + ) + .expect_get_buffer_bytes(Some(BufferType::GrpcReceiveBuffer)) + .returning(Some(&vec![])) + .expect_send_local_response( + Some(500), + Some("Internal Server Error.\n"), + Some(vec![]), + Some(-1), + ) + .execute_and_expect(ReturnType::None) + .unwrap(); +} + +#[test] +#[serial] +fn it_fails_on_second_action_grpc_response() { + // this usually happens when target service is registered on host but unreachable + let args = tester::MockSettings { + wasm_path: wasm_module(), + quiet: false, + allow_unexpected: false, + }; + let mut module = tester::mock(args).unwrap(); + + module + .call_start() + .execute_and_expect(ReturnType::None) + .unwrap(); + + let root_context = 1; + let cfg = r#"{ + "services": { + "limitador": { + "type": "ratelimit", + "endpoint": "limitador-cluster", + "failureMode": "deny", + "timeout": "5s" + }, + "limitador-unreachable": { + "type": "ratelimit", + "endpoint": "unreachable-cluster", + "failureMode": "deny", + "timeout": "5s" + } + }, + "actionSets": [ + { + "name": "some-name", + "routeRuleConditions": { + "hostnames": ["example.com"] + }, + "actions": [ + { + "service": "limitador", + "scope": "a", + "data": [ + { + "expression": { + "key": "limit_to_be_activated", + "value": "1" + } + } + ] + }, + { + "service": "limitador-unreachable", + "scope": "a", + "data": [ + { + "expression": { + "key": "limit_to_be_activated", + "value": "1" + } + } + ] + }] + }] + }"#; + + module + .call_proxy_on_context_create(root_context, 0) + .expect_log(Some(LogLevel::Info), Some("#1 set_root_context")) + .execute_and_expect(ReturnType::None) + .unwrap(); + module + .call_proxy_on_configure(root_context, 0) + .expect_log(Some(LogLevel::Info), Some("#1 on_configure")) + .expect_get_buffer_bytes(Some(BufferType::PluginConfiguration)) + .returning(Some(cfg.as_bytes())) + .expect_log(Some(LogLevel::Info), None) + .execute_and_expect(ReturnType::Bool(true)) + .unwrap(); + + let http_context = 2; + let first_call_token_id = 42; + module + .call_proxy_on_context_create(http_context, root_context) + .expect_log(Some(LogLevel::Debug), Some("#2 create_http_context")) + .execute_and_expect(ReturnType::None) + .unwrap(); + + module + .call_proxy_on_request_headers(http_context, 0, false) + .expect_log(Some(LogLevel::Debug), Some("#2 on_http_request_headers")) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some(":authority")) + .returning(Some("example.com")) + .expect_log( + Some(LogLevel::Debug), + Some("#2 action_set selected some-name"), + ) + // retrieving tracing headers + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("traceparent")) + .returning(None) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("tracestate")) + .returning(None) + .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("baggage")) + .returning(None) + .expect_grpc_call( + Some("limitador-cluster"), + Some("envoy.service.ratelimit.v3.RateLimitService"), + Some("ShouldRateLimit"), + Some(&[0, 0, 0, 0]), + Some(&[ + 10, 1, 97, 18, 28, 10, 26, 10, 21, 108, 105, 109, 105, 116, 95, 116, 111, 95, 98, + 101, 95, 97, 99, 116, 105, 118, 97, 116, 101, 100, 18, 1, 49, 24, 1, + ]), + Some(5000), + ) + .returning(Ok(first_call_token_id)) + .expect_log( + Some(LogLevel::Debug), + Some(format!("#2 initiated gRPC call (id# {first_call_token_id})").as_str()), + ) + .execute_and_expect(ReturnType::Action(Action::Pause)) + .unwrap(); + + let grpc_response: [u8; 2] = [8, 1]; + let second_call_token_id = first_call_token_id + 1; + module + .call_proxy_on_grpc_receive( + http_context, + first_call_token_id as i32, + grpc_response.len() as i32, + ) + .expect_log( + Some(LogLevel::Debug), + Some("#2 on_grpc_call_response: received gRPC call response: token: 42, status: 0"), + ) + .expect_get_buffer_bytes(Some(BufferType::GrpcReceiveBuffer)) + .returning(Some(&grpc_response)) + .expect_grpc_call( + Some("unreachable-cluster"), + Some("envoy.service.ratelimit.v3.RateLimitService"), + Some("ShouldRateLimit"), + Some(&[0, 0, 0, 0]), + Some(&[ + 10, 1, 97, 18, 28, 10, 26, 10, 21, 108, 105, 109, 105, 116, 95, 116, 111, 95, 98, + 101, 95, 97, 99, 116, 105, 118, 97, 116, 101, 100, 18, 1, 49, 24, 1, + ]), + Some(5000), + ) + .returning(Ok(second_call_token_id)) + .execute_and_expect(ReturnType::None) + .unwrap(); + + let status_code = 14; + module + .proxy_on_grpc_close(http_context, second_call_token_id as i32, status_code) + .expect_log( + Some(LogLevel::Debug), + Some(format!( + "#2 on_grpc_call_response: received gRPC call response: token: {second_call_token_id}, status: {status_code}" + ).as_str()), + ) + .expect_get_buffer_bytes(Some(BufferType::GrpcReceiveBuffer)) + .returning(Some(&vec![])) + .expect_send_local_response( + Some(500), + Some("Internal Server Error.\n"), + Some(vec![]), + Some(-1), + ) + .execute_and_expect(ReturnType::None) + .unwrap(); +} diff --git a/tests/multi.rs b/tests/multi.rs index 20a11bfd..e1d1663b 100644 --- a/tests/multi.rs +++ b/tests/multi.rs @@ -210,7 +210,7 @@ fn it_performs_authenticated_rate_limiting() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"), @@ -242,7 +242,7 @@ fn it_performs_authenticated_rate_limiting() { ]), Some(5000), ) - .returning(Some(43)) + .returning(Ok(43)) .execute_and_expect(ReturnType::None) .unwrap(); @@ -424,7 +424,7 @@ fn unauthenticated_does_not_ratelimit() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"), @@ -698,7 +698,7 @@ fn authenticated_one_ratelimit_action_matches() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"), @@ -743,7 +743,7 @@ fn authenticated_one_ratelimit_action_matches() { ]), Some(5000), ) - .returning(Some(43)) + .returning(Ok(43)) .execute_and_expect(ReturnType::None) .unwrap(); diff --git a/tests/rate_limited.rs b/tests/rate_limited.rs index 1586160b..b816abef 100644 --- a/tests/rate_limited.rs +++ b/tests/rate_limited.rs @@ -186,7 +186,7 @@ fn it_limits() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"), @@ -332,7 +332,7 @@ fn it_passes_additional_headers() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"), @@ -468,7 +468,7 @@ fn it_rate_limits_with_empty_predicates() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"), @@ -711,7 +711,7 @@ fn it_folds_subsequent_actions_to_limitador_into_a_single_one() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"), diff --git a/tests/remote_address.rs b/tests/remote_address.rs index 4e6fe821..3d25e99a 100644 --- a/tests/remote_address.rs +++ b/tests/remote_address.rs @@ -121,7 +121,7 @@ fn it_limits_based_on_source_address() { ]), Some(5000), ) - .returning(Some(42)) + .returning(Ok(42)) .expect_log( Some(LogLevel::Debug), Some("#2 initiated gRPC call (id# 42)"),