Examples

Examples #

Practical examples organized by use case. Each example can be copied and run directly.


1. Bulk Write Benchmarking #

Goal: Evaluate write throughput, cluster load, and queue pressure.

# variables: [
#   {name: "id", type: "sequence"},
#   {name: "uuid", type: "uuid"},
#   {name: "suffix", type: "range", from: 1, to: 100},
#   {name: "ip", type: "file", path: "dict/ip.txt"},
#   {name: "now_unix", type: "now_unix"},
# ],

POST $[[env.ES_ENDPOINT]]/_bulk
{"index": {"_index": "bench-$[[suffix]]", "_id": "$[[uuid]]", "routing": "$[[routing_no]]"}}
{"id": "$[[id]]", "ip": "$[[ip]]", "batch": "$[[batch_no]]", "ts": "$[[now_unix]]"}
# request: {
#   basic_auth: {
#     username: "$[[env.ES_USERNAME]]",
#     password: "$[[env.ES_PASSWORD]]",
#   },
#   runtime_variables: {
#     batch_no: "uuid",
#   },
#   runtime_body_line_variables: {
#     routing_no: "uuid",
#   },
#   body_repeat_times: 1000,
# },

Run commands:

# Sustained 60 seconds, 100 concurrent threads
loadgen -d 60 -c 100

# Fixed QPS
loadgen -d 60 -c 100 -r 2000

# Fixed total request count
loadgen -d 600 -c 100 -l 50000

Reference: testing/setup/loadgen/cases/bulk/create.yml


2. Search Performance Testing #

Goal: Evaluate query latency and throughput across different query patterns.

# variables: [
#   {name: "user", type: "file", path: "dict/user.txt"},
#   {name: "ip", type: "file", path: "dict/ip.txt"},
# ],

GET $[[env.ES_ENDPOINT]]/my-index/_search?q=user:$[[user]]
# request: {
#   basic_auth: {
#     username: "$[[env.ES_USERNAME]]",
#     password: "$[[env.ES_PASSWORD]]",
#   },
# },

Run command:

loadgen -d 30 -c 10

Reference: testing/setup/loadgen/cases/search/random_search.yml


3. Mixed Request Benchmarking #

Goal: Simulate real-world traffic with create + update + delete mixed workload.

A single DSL file with multiple requests — Loadgen executes them sequentially in a loop:

# variables: [
#   {name: "id", type: "sequence"},
#   {name: "uuid", type: "uuid"},
#   {name: "user", type: "list", data: ["alice", "bob", "test"]},
# ],

POST $[[env.ES_ENDPOINT]]/_bulk
{"index": {"_index": "mixed-test", "_id": "$[[uuid]]"}}
{"id": "$[[id]]", "user": "$[[user]]"}
# request: {
#   body_repeat_times: 10,
# },

POST $[[env.ES_ENDPOINT]]/_bulk
{"delete": {"_index": "mixed-test", "_id": "$[[uuid]]"}}
# request: {
#   body_repeat_times: 5,
# },

Reference: testing/setup/loadgen/cases/bulk/mixed.yml


4. Functional Validation & CI Integration #

Goal: Execute all requests once, assert everything passes, then exit.

# runner: {
#   total_rounds: 1,
#   no_warm: true,
#   assert_invalid: true,
#   assert_error: true,
# },

GET $[[env.ES_ENDPOINT]]/_cluster/health
# assert: {
#   _ctx.response.status: 200,
# },

GET $[[env.ES_ENDPOINT]]/_cat/indices
# assert: {
#   _ctx.response.status: 200,
# },

Run command:

loadgen -run health_check.dsl
echo $?  # 0=pass, 1=assertion failure, 2=request error

Ideal for CI pipelines — any assertion failure causes a non-zero exit.

Reference: testing/setup/loadgen/cases/dummy/loadgen.yml


5. Dynamic Variable Registration (Chain Testing) #

Goal: Extract values from preceding requests for use in subsequent ones.

# runner: {
#   total_rounds: 1,
#   no_warm: true,
#   assert_invalid: true,
# },

# Create a document, extract the generated _id
POST $[[env.ES_ENDPOINT]]/my-index/_doc
{"title": "test document", "user": "loadgen"}
# assert: {
#   _ctx.response.status: 201,
# },
# register: [
#   { doc_id: "_ctx.response.body_json._id" },
# ]

# Read the document using the registered doc_id
GET $[[env.ES_ENDPOINT]]/my-index/_doc/$[[doc_id]]
# assert: {
#   _ctx.response.status: 200,
#   _ctx.response.body_json._source.user: "loadgen",
# },

# Delete the document
DELETE $[[env.ES_ENDPOINT]]/my-index/_doc/$[[doc_id]]
# assert: {
#   _ctx.response.status: 200,
# },

Reference: testing/setup/easysearch/cases/crud/create_without_id/loadgen.yml


6. JSON Response Assertions #

Goal: Validate specific fields in JSON response bodies.

GET $[[env.ES_ENDPOINT]]/my-index/_search
{"query": {"match_all": {}}}
# assert: {
#   _ctx.response.status: 200,
#   _ctx.response.body_json.hits.total.value: 100,
#   _ctx.response.body_json.timed_out: false,
# },

Shorthand assertion format:

GET /api/status
# assert: (200, {status: "ok", version: "1.0"}),

Reference: testing/setup/gateway/cases/filters/set_response/loadgen.yml


7. Authenticated API Testing (Token Mode) #

Goal: Login to get a token, then use it in subsequent requests via headers.

# runner: {
#   total_rounds: 1,
#   no_warm: true,
#   assert_invalid: true,
#   default_endpoint: "$[[env.API_HOST]]",
# },

# Login
POST /account/login
{"email": "admin@example.com", "password": "$[[env.ADMIN_PASSWORD]]"}
# assert: (200, {}),
# register: [
#   { token: "_ctx.response.body_json.access_token" },
# ]

# Use token to call a business API
GET /api/resources?size=10
# request: {
#   headers: [
#     {Authorization: "Bearer $[[token]]"},
#   ],
#   disable_header_names_normalizing: true,
# },
# assert: {
#   _ctx.response.status: 200,
# },

# Create a resource
POST /api/resources
{"name": "test-resource", "type": "demo"}
# request: {
#   headers: [
#     {Authorization: "Bearer $[[token]]"},
#   ],
#   disable_header_names_normalizing: true,
# },
# assert: (200, {}),
# register: [
#   { resource_id: "_ctx.response.body_json.id" },
# ]

# Delete the resource
DELETE /api/resources/$[[resource_id]]
# request: {
#   headers: [
#     {Authorization: "Bearer $[[token]]"},
#   ],
#   disable_header_names_normalizing: true,
# },
# assert: {
#   _ctx.response.status: 200,
# },

8. Coco AI Integration Testing #

We use Loadgen for full integration testing in the Coco Server project:

Project Structure #

tests/
├── loadgen.yml              # Global config (env vars, runner)
├── assets/
│   ├── run_integration_tests.py   # Auto-execute all scenarios
│   ├── start_coco.sh
│   ├── stop_coco.sh
│   └── reset_coco_indices.sh
├── llm/
│   ├── scenario1.dsl
│   ├── scenario2.dsl
│   └── scenario3.dsl
├── assistant/
│   └── scenario1.dsl
└── datasource/
    └── scenario1.dsl

Global Configuration #

# tests/loadgen.yml
runner:
  total_rounds: 1
  no_warm: true
  reset_context: true
  assert_invalid: true
  default_endpoint: "$[[env.COCO_SERVER]]"

env:
  COCO_SERVER: http://127.0.0.1:9000
  ADMIN_PASSWORD: PASSword_123

Single Scenario Debugging #

cd coco
loadgen -config ./tests/loadgen.yml -run ./tests/llm/scenario3.dsl -debug

Full Regression Testing #

cd coco
python3 ./tests/assets/run_integration_tests.py

The script automatically: stops environment → resets data → starts service → executes each DSL → cleans up.


9. Project Organization #

Recommended test project structure:

project/
├── loadgen.yml              # Global configuration
├── dict/                    # Corpus files
│   ├── ip.txt
│   ├── user.txt
│   └── keywords.txt
├── cases/                   # Test cases grouped by function
│   ├── bulk/
│   │   ├── create.dsl
│   │   └── mixed.dsl
│   ├── search/
│   │   └── random.dsl
│   └── crud/
│       └── lifecycle.dsl
└── suites/                  # Suite configs (batch run multiple cases)
    └── regression.yml

Corpus file example (dict/ip.txt):

192.168.1.1
10.0.0.1
172.16.0.100

One value per line; a random line is picked for each request.

Reference repositories:


10. Command Quick Reference #

# Basic benchmark (60 seconds, 100 concurrent)
loadgen -run bench.dsl -d 60 -c 100

# Fixed QPS
loadgen -run bench.dsl -d 60 -c 100 -r 1000

# Fixed total requests
loadgen -run bench.dsl -d 600 -c 100 -l 50000

# Enable gzip compression
loadgen -run bench.dsl -d 60 -c 100 -compress

# Functional validation (single execution)
loadgen -run test.dsl

# Specify config file
loadgen -run test.dsl -config env/production.yml

# Debug mode
loadgen -run test.dsl -debug
Edit Edit this page