extproctor

module
v0.0.0-...-f610707 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 17, 2025 License: MIT

README ΒΆ

πŸ§ͺ ExtProctor

A test runner for Envoy ExtProc implementations

Go Version License Go Report Card Documentation

Features β€’ Installation β€’ Quick Start β€’ Documentation β€’ Examples β€’ Contributing


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

License

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


Made with ❀️ for the Envoy community

Directories ΒΆ

Path Synopsis
cmd
extproctor command
gen
internal
cli
sample
extproc command
Package main implements a simple Envoy External Processor (ExtProc) filter.
Package main implements a simple Envoy External Processor (ExtProc) filter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL