Skip to content

Commit a149800

Browse files
authored
feat(e2e): Add comprehensive signal-decision engine test coverage (#695)
1 parent ee6e87e commit a149800

File tree

15 files changed

+1972
-124
lines changed

15 files changed

+1972
-124
lines changed

deploy/kubernetes/aibrix/semantic-router-values/values.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ config:
3535
- name: computer science
3636
- name: philosophy
3737
- name: engineering
38-
- name: thinking
3938

4039
# Decisions - define routing logic with rules, model selection, and plugins
4140
decisions:
@@ -365,7 +364,7 @@ config:
365364
rules:
366365
operator: "OR"
367366
conditions:
368-
- type: "domain"
367+
- type: "keyword"
369368
name: "thinking"
370369
modelRefs:
371370
- model: vllm-llama3-8b-instruct
@@ -445,7 +444,7 @@ config:
445444
pii_mapping_path: "models/pii_classifier_modernbert-base_presidio_token_model/pii_type_mapping.json"
446445

447446
keyword_rules:
448-
- category: "thinking"
447+
- name: "thinking"
449448
operator: "OR"
450449
keywords: ["urgent", "immediate", "asap", "think", "careful"]
451450
case_sensitive: false

e2e/README.md

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ e2e/
3939
│ ├── domain_classify.go
4040
│ ├── cache.go
4141
│ ├── pii_detection.go
42-
│ └── jailbreak_detection.go
42+
│ ├── jailbreak_detection.go
43+
│ ├── decision_priority.go # Signal-decision: Priority selection
44+
│ ├── plugin_chain_execution.go # Signal-decision: Plugin chains
45+
│ ├── rule_condition_logic.go # Signal-decision: AND/OR operators
46+
│ ├── decision_fallback.go # Signal-decision: Fallback behavior
47+
│ ├── keyword_routing.go # Signal-decision: Keyword matching
48+
│ └── plugin_config_variations.go # Signal-decision: Plugin configs
4349
├── profiles/
4450
│ └── ai-gateway/ # AI Gateway test profile
4551
│ └── profile.go # Profile definition and environment setup
@@ -50,19 +56,48 @@ e2e/
5056

5157
The framework includes the following test cases (all in `e2e/testcases/`):
5258

59+
### Basic Functionality Tests
60+
5361
| Test Case | Description | Metrics |
5462
|-----------|-------------|---------|
5563
| `chat-completions-request` | Basic chat completions API test | Response validation |
5664
| `chat-completions-stress-request` | Sequential stress test with 1000 requests | Success rate, avg duration |
5765
| `chat-completions-progressive-stress` | Progressive QPS stress test (10/20/50/100 QPS) | Per-stage success rate, latency stats |
66+
67+
### Classification and Feature Tests
68+
69+
| Test Case | Description | Metrics |
70+
|-----------|-------------|---------|
5871
| `domain-classify` | Domain classification accuracy | 65 cases, accuracy rate |
5972
| `semantic-cache` | Semantic cache hit rate | 5 groups, cache hit rate |
6073
| `pii-detection` | PII detection and blocking | 10 PII types, detection rate, block rate |
6174
| `jailbreak-detection` | Jailbreak attack detection | 10 attack types, detection rate, block rate |
6275

76+
### Signal-Decision Engine Tests
77+
78+
| Test Case | Description | Metrics |
79+
|-----------|-------------|---------|
80+
| `decision-priority-selection` | Decision priority selection with multiple matches | 4 cases, priority validation (indirect) |
81+
| `plugin-chain-execution` | Plugin execution order (PII → Cache → System Prompt) | 4 cases, chain validation, blocking behavior |
82+
| `rule-condition-logic` | AND/OR operators and keyword matching | 6 cases, operator validation |
83+
| `decision-fallback-behavior` | Fallback to default decision when no match | 5 cases, fallback validation |
84+
| `keyword-routing` | Keyword-based routing decisions | 6 cases, keyword matching (case-insensitive) |
85+
| `plugin-config-variations` | Plugin configuration variations (PII allowlist, cache thresholds) | 6 cases, config validation |
86+
87+
**Signal-Decision Engine Features Tested:**
88+
89+
- ✅ Decision priority selection (priority 15 > 10) - validated by checking which decision wins when multiple match
90+
- ✅ Plugin chain execution order and blocking
91+
- ✅ Rule condition logic (AND/OR operators)
92+
- ✅ Keyword-based routing (case-insensitive)
93+
- ✅ Decision fallback behavior
94+
- ✅ Per-decision plugin configurations
95+
- ✅ PII allowlist handling
96+
- ✅ Per-decision cache thresholds (0.75, 0.92, 0.95)
97+
6398
All test cases:
6499

65-
- Use model name `"MoM"`
100+
- Use model name `"MoM"` to trigger decision engine
66101
- Automatically clean up port forwarding
67102
- Generate detailed reports with statistics
68103
- Support verbose logging
@@ -312,6 +347,15 @@ Test data is stored in `e2e/testcases/testdata/` as JSON files. Each test case l
312347
- `pii_detection_cases.json`: 10 PII types (email, phone, SSN, etc.)
313348
- `jailbreak_detection_cases.json`: 10 attack types (prompt injection, DAN, etc.)
314349

350+
**Signal-Decision Engine Tests** use embedded test cases (defined inline in test files) to validate:
351+
352+
- Decision priority mechanisms (4 test cases)
353+
- Plugin chain execution and blocking (4 test cases)
354+
- Rule condition logic with AND/OR operators (6 test cases)
355+
- Decision fallback behavior (5 test cases)
356+
- Keyword-based routing (6 test cases)
357+
- Plugin configuration variations (6 test cases)
358+
315359
**Test Data Format Example:**
316360

317361
```json

e2e/profiles/ai-gateway/profile.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,27 @@ func (p *Profile) Teardown(ctx context.Context, opts *framework.TeardownOptions)
107107
// GetTestCases returns the list of test cases for this profile
108108
func (p *Profile) GetTestCases() []string {
109109
return []string{
110+
// Basic functionality tests
110111
"chat-completions-request",
111112
"chat-completions-stress-request",
113+
114+
// Classification and routing tests
112115
"domain-classify",
116+
117+
// Feature tests
113118
"semantic-cache",
114119
"pii-detection",
115120
"jailbreak-detection",
121+
122+
// Signal-Decision engine tests (new architecture)
123+
"decision-priority-selection", // Priority-based routing
124+
"plugin-chain-execution", // Plugin ordering and blocking
125+
"rule-condition-logic", // AND/OR operators
126+
"decision-fallback-behavior", // Fallback to default
127+
"keyword-routing", // Keyword-based decisions
128+
"plugin-config-variations", // Plugin configuration testing
129+
130+
// Load tests
116131
"chat-completions-progressive-stress",
117132
}
118133
}

e2e/profiles/ai-gateway/values.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ config:
367367
operator: "OR"
368368
conditions:
369369
- type: "keyword"
370-
rule_name: "thinking"
370+
name: "thinking"
371371
modelRefs:
372372
- model: base-model
373373
lora_name: general-expert
@@ -383,7 +383,7 @@ config:
383383
system_prompt: "You are a thinking expert, should think multiple steps before answering. Please answer the question step by step."
384384
mode: "replace"
385385

386-
- name: general_decision
386+
- name: other_decision
387387
description: "General knowledge and miscellaneous topics"
388388
priority: 1
389389
rules:
@@ -474,7 +474,7 @@ config:
474474
pii_mapping_path: "models/pii_classifier_modernbert-base_presidio_token_model/pii_type_mapping.json"
475475

476476
keyword_rules:
477-
- category: "thinking"
477+
- name: "thinking"
478478
operator: "OR"
479479
keywords: ["urgent", "immediate", "asap", "think", "careful"]
480480
case_sensitive: false

e2e/profiles/aibrix/profile.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,27 @@ func (p *Profile) Teardown(ctx context.Context, opts *framework.TeardownOptions)
167167
// GetTestCases returns the list of test cases for this profile
168168
func (p *Profile) GetTestCases() []string {
169169
return []string{
170+
// Basic functionality tests
170171
"chat-completions-request",
171172
"chat-completions-stress-request",
173+
174+
// Classification and routing tests
172175
"domain-classify",
176+
177+
// Feature tests
173178
"semantic-cache",
174179
"pii-detection",
175180
"jailbreak-detection",
181+
182+
// Signal-Decision engine tests (new architecture)
183+
"decision-priority-selection", // Priority-based routing
184+
"plugin-chain-execution", // Plugin ordering and blocking
185+
"rule-condition-logic", // AND/OR operators
186+
"decision-fallback-behavior", // Fallback to default
187+
"keyword-routing", // Keyword-based decisions
188+
"plugin-config-variations", // Plugin configuration testing
189+
190+
// Load tests
176191
"chat-completions-progressive-stress",
177192
}
178193
}

e2e/profiles/dynamic-config/crds/intelligentroute.yaml

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,36 @@ spec:
3535
- name: "other"
3636
description: "General knowledge and miscellaneous topics"
3737

38+
keywords:
39+
- name: "thinking"
40+
operator: "OR"
41+
keywords: ["urgent", "immediate", "asap", "think", "careful"]
42+
caseSensitive: false
43+
3844
decisions:
45+
- name: "thinking_decision"
46+
priority: 15
47+
description: "Queries requiring careful thought or urgent attention"
48+
signals:
49+
operator: "OR"
50+
conditions:
51+
- type: "keyword"
52+
name: "thinking"
53+
modelRefs:
54+
- model: "base-model"
55+
loraName: "math-expert"
56+
useReasoning: true
57+
plugins:
58+
- type: "pii"
59+
configuration:
60+
enabled: true
61+
pii_types_allowed: []
62+
- type: "system_prompt"
63+
configuration:
64+
enabled: true
65+
system_prompt: "You are a thoughtful assistant trained to approach problems systematically. When handling urgent matters or complex questions, break down the problem into clear steps, consider multiple angles, and provide thorough, well-reasoned responses. Take your time to think through implications and edge cases."
66+
mode: "replace"
67+
3968
- name: "business_decision"
4069
priority: 10
4170
description: "Business and management related queries"
@@ -328,6 +357,27 @@ spec:
328357
conditions:
329358
- type: "domain"
330359
name: "engineering"
360+
modelRefs:
361+
- model: "base-model"
362+
loraName: "science-expert"
363+
useReasoning: false
364+
plugins:
365+
- type: "pii"
366+
configuration:
367+
enabled: true
368+
pii_types_allowed: []
369+
- type: "system_prompt"
370+
configuration:
371+
enabled: true
372+
system_prompt: "You are an engineering expert with knowledge across multiple engineering disciplines including mechanical, electrical, civil, chemical, software, and systems engineering. Apply engineering principles, design methodologies, and problem-solving approaches to provide practical solutions. Consider safety, efficiency, sustainability, and cost-effectiveness in your recommendations. Use technical precision while explaining concepts clearly, and emphasize the importance of proper engineering practices and standards."
373+
mode: "replace"
374+
375+
- name: "other_decision"
376+
priority: 1
377+
description: "General knowledge and miscellaneous topics"
378+
signals:
379+
operator: "OR"
380+
conditions:
331381
- type: "domain"
332382
name: "other"
333383
modelRefs:
@@ -339,8 +389,12 @@ spec:
339389
configuration:
340390
enabled: true
341391
pii_types_allowed: []
392+
- type: "semantic-cache"
393+
configuration:
394+
enabled: true
395+
similarity_threshold: 0.75
342396
- type: "system_prompt"
343397
configuration:
344398
enabled: true
345-
system_prompt: "You are an engineering expert with knowledge across multiple engineering disciplines including mechanical, electrical, civil, chemical, software, and systems engineering. Apply engineering principles, design methodologies, and problem-solving approaches to provide practical solutions. Consider safety, efficiency, sustainability, and cost-effectiveness in your recommendations. Use technical precision while explaining concepts clearly, and emphasize the importance of proper engineering practices and standards."
399+
system_prompt: "You are a knowledgeable AI assistant with broad expertise across many domains. Provide accurate, helpful, and well-structured responses to general questions. When uncertain, acknowledge limitations and suggest where to find authoritative information."
346400
mode: "replace"

e2e/profiles/dynamic-config/profile.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,27 @@ func (p *Profile) Teardown(ctx context.Context, opts *framework.TeardownOptions)
104104
// GetTestCases returns the list of test cases for this profile
105105
func (p *Profile) GetTestCases() []string {
106106
return []string{
107+
// Basic functionality tests
107108
"chat-completions-request",
108109
"chat-completions-stress-request",
110+
111+
// Classification and routing tests
109112
"domain-classify",
113+
114+
// Feature tests
110115
"semantic-cache",
111116
"pii-detection",
112117
"jailbreak-detection",
118+
119+
// Signal-Decision engine tests (new architecture)
120+
"decision-priority-selection", // Priority-based routing
121+
"plugin-chain-execution", // Plugin ordering and blocking
122+
"rule-condition-logic", // AND/OR operators
123+
"decision-fallback-behavior", // Fallback to default
124+
"keyword-routing", // Keyword-based decisions
125+
"plugin-config-variations", // Plugin configuration testing
126+
127+
// Load tests
113128
"chat-completions-progressive-stress",
114129
}
115130
}

e2e/testcases/common.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,11 @@ func formatResponseHeaders(headers map[string][]string) string {
144144
}
145145
return sb.String()
146146
}
147+
148+
// truncateString truncates a string to maxLen characters, adding "..." if truncated
149+
func truncateString(s string, maxLen int) string {
150+
if len(s) <= maxLen {
151+
return s
152+
}
153+
return s[:maxLen-3] + "..."
154+
}

0 commit comments

Comments
 (0)