Skip to content

ExtProctor is a test runner for Envoy External Processing (ExtProc) implementations. Define test cases using human-readable prototext manifests, validate expected behaviours across all processing phases (headers, body, trailers), and integrate seamlessly into CI/CD pipelines with JSON output and golden file support.

License

Notifications You must be signed in to change notification settings

zntrio/extproctor

Repository files navigation

🧪 ExtProctor

A test runner for Envoy ExtProc implementations

Go Version License Go Report Card Documentation

FeaturesInstallationQuick StartDocumentationExamplesContributing


Why ExtProctor?

Implementing and evolving Envoy External Processing (ExtProc) services is error-prone. Behaviours depend on correct protobuf message structures and a sequence of callbacks that are difficult to test manually.

Note

This project is heavily inspired by Google Service Extensions where they use the same approach to test their service extensions.

ExtProctor provides a dedicated test runner that enables:

  • Automated regression testing for ExtProc implementations
  • Fast feedback loops during local development
  • CI/CD integration with machine-readable outputs
  • Version-controlled test cases using human-readable prototext manifests

Features

Feature Description
📝 Prototext Manifests Define test cases using human-readable prototext format
🔄 Full ExtProc Support Test all processing phases: headers, body, and trailers
📸 Golden Files Capture and compare responses using the golden file pattern
Parallel Execution Run tests concurrently for faster feedback
🏷️ Flexible Filtering Filter tests by name pattern or tags
📊 Multiple Output Formats Human-readable or JSON output for CI integration
🔌 Unix Socket Support Connect to ExtProc services via Unix domain sockets
🔒 TLS Support Secure gRPC connections with client certificates

Installation

Using Go

go install zntr.io/extproctor/cmd/extproctor@latest

From Source

git clone https://github.com/zntrio/extproctor.git
cd extproctor
go build -o extproctor ./cmd/extproctor

Verify Installation

extproctor --help

Quick Start

1. Create a Test Manifest

Create a file tests/basic.textproto:

name: "basic-test"
description: "Basic ExtProc test"

test_cases: {
  name: "add-header"
  description: "Verify ExtProc adds a custom header"
  tags: ["smoke"]

  request: {
    method: "GET"
    path: "/api/v1/users"
    scheme: "https"
    authority: "api.example.com"
    headers: {
      key: "content-type"
      value: "application/json"
    }
  }

  expectations: {
    phase: REQUEST_HEADERS
    headers_response: {
      set_headers: {
        key: "x-custom-header"
        value: "custom-value"
      }
    }
  }
}

2. Run the Tests

extproctor run ./tests/ --target localhost:50051

3. View Results

Running tests from 1 manifest(s)...

✓ basic-test/add-header (12ms)

Results: 1 passed, 0 failed, 0 skipped

Documentation

CLI Commands

extproctor run

Execute tests against an ExtProc service.

# Run all tests in a directory
extproctor run ./tests/ --target localhost:50051

# Run with Unix domain socket
extproctor run ./tests/ --unix-socket /var/run/extproc.sock

# Run with parallel execution
extproctor run ./tests/ --target localhost:50051 --parallel 4

# Filter by test name pattern
extproctor run ./tests/ --target localhost:50051 --filter "auth*"

# Filter by tags
extproctor run ./tests/ --target localhost:50051 --tags "smoke,regression"

# JSON output for CI pipelines
extproctor run ./tests/ --target localhost:50051 --output json

# Verbose mode for debugging
extproctor run ./tests/ --target localhost:50051 -v

# Update golden files
extproctor run ./tests/ --target localhost:50051 --update-golden

extproctor validate

Validate manifest syntax without running tests.

# Validate all manifests in a directory
extproctor validate ./tests/

# Validate specific files
extproctor validate test1.textproto test2.textproto

Command-Line Options

Flag Description Default
--target ExtProc service address (host:port) localhost:50051
--unix-socket Unix domain socket path
--tls Enable TLS for gRPC connection false
--tls-cert TLS client certificate file
--tls-key TLS client key file
--tls-ca TLS CA certificate file
-p, --parallel Number of parallel test executions 1
-o, --output Output format (human, json) human
-v, --verbose Enable verbose output false
--filter Filter tests by name pattern
--tags Filter tests by tags (comma-separated)
--update-golden Update golden files with actual responses false

Note: --target and --unix-socket are mutually exclusive.

Manifest Format

Test manifests are written in Prototext format.

Structure

name: "manifest-name"
description: "Description of the test suite"

test_cases: {
  name: "test-case-name"
  description: "What this test validates"
  tags: ["tag1", "tag2"]

  request: {
    method: "POST"
    path: "/api/endpoint"
    scheme: "https"
    authority: "api.example.com"
    headers: {
      key: "content-type"
      value: "application/json"
    }
    body: '{"key": "value"}'
    process_request_body: true
    process_response_headers: true
  }

  expectations: {
    phase: REQUEST_HEADERS
    headers_response: {
      set_headers: {
        key: "x-custom"
        value: "value"
      }
    }
  }
}

Processing Phases

Phase Description
REQUEST_HEADERS Processing request headers
REQUEST_BODY Processing request body
REQUEST_TRAILERS Processing request trailers
RESPONSE_HEADERS Processing response headers
RESPONSE_BODY Processing response body
RESPONSE_TRAILERS Processing response trailers

Expectation Types

Headers Response
expectations: {
  phase: REQUEST_HEADERS
  headers_response: {
    set_headers: {
      key: "x-custom"
      value: "value"
    }
    remove_headers: "x-internal"
    append_headers: {
      key: "x-multi"
      value: "value"
    }
  }
}
Body Response
expectations: {
  phase: REQUEST_BODY
  body_response: {
    body: '{"modified": true}'
    common_response: {
      status: CONTINUE_AND_REPLACE
    }
  }
}
Trailers Response
expectations: {
  phase: REQUEST_TRAILERS
  trailers_response: {
    set_trailers: {
      key: "x-checksum-validated"
      value: "true"
    }
  }
}
Immediate Response (Short-circuit)
expectations: {
  phase: REQUEST_HEADERS
  immediate_response: {
    status_code: 403
    headers: {
      key: "content-type"
      value: "application/json"
    }
    body: '{"error": "forbidden"}'
  }
}

Golden Files

Use golden files for snapshot testing:

test_cases: {
  name: "golden-test"
  request: { ... }
  golden_file: "golden/test-response.textproto"
}

Update golden files when behavior changes intentionally:

extproctor run ./tests/ --target localhost:50051 --update-golden

Examples

The testdata/examples/ directory contains complete example manifests:

File Description
basic_headers.textproto Basic header processing (add/remove headers)
auth_flow.textproto Authentication flow with immediate response rejection
body_processing.textproto Request body inspection and transformation
multi_phase_flow.textproto Multi-phase processing across request/response lifecycle

Sample ExtProc Server

A sample ExtProc server is included for testing and reference:

# Start the sample server
go run ./sample/extproc/ --addr :50051

# Run tests against it
extproctor run ./sample/extproc/test/ --target localhost:50051

The sample server demonstrates:

  • Request headers processing with custom header injection
  • Request/response body handling
  • Response headers modification
  • gRPC health check endpoint

Development

Prerequisites

Building

go build -o extproctor ./cmd/extproctor

Running Tests

go test ./...

Regenerating Protobuf Code

buf generate

Project Structure

extproctor/
├── cmd/extproctor/          # CLI entry point
├── internal/
│   ├── cli/              # Command-line interface
│   ├── client/           # ExtProc gRPC client
│   ├── comparator/       # Response comparison logic
│   ├── golden/           # Golden file handling
│   ├── manifest/         # Manifest loading and validation
│   ├── reporter/         # Test result reporting
│   └── runner/           # Test execution engine
├── proto/                # Protobuf definitions
├── sample/extproc/       # Sample ExtProc server
└── testdata/examples/    # Example test manifests

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Please make sure to:

  • Update tests as appropriate
  • Follow the existing code style
  • Update documentation for any new features

Related Resources

License

This project is licensed under the MIT License - see the LICENSE file for details.


Made with ❤️ for the Envoy community

About

ExtProctor is a test runner for Envoy External Processing (ExtProc) implementations. Define test cases using human-readable prototext manifests, validate expected behaviours across all processing phases (headers, body, trailers), and integrate seamlessly into CI/CD pipelines with JSON output and golden file support.

Resources

License

Stars

Watchers

Forks

Packages

No packages published