Skip to content

Commit 17a1c5a

Browse files
committed
fix: unit_test
Signed-off-by: OneZero-Y <[email protected]>
1 parent d05c2f9 commit 17a1c5a

File tree

2 files changed

+81
-34
lines changed

2 files changed

+81
-34
lines changed

src/semantic-router/pkg/api/server.go

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package api
22

33
import (
4+
"bytes"
45
"encoding/json"
56
"fmt"
67
"io"
@@ -251,22 +252,57 @@ func (s *ClassificationAPIServer) handleCombinedClassification(w http.ResponseWr
251252
}
252253

253254
func (s *ClassificationAPIServer) handleBatchClassification(w http.ResponseWriter, r *http.Request) {
255+
// Record batch classification request
256+
metrics.RecordBatchClassificationRequest("unified")
257+
258+
// Start timing for duration metrics
259+
start := time.Now()
260+
261+
// First, read the raw body to check if texts field exists
262+
body, err := io.ReadAll(r.Body)
263+
if err != nil {
264+
metrics.RecordBatchClassificationError("unified", "read_body_failed")
265+
s.writeErrorResponse(w, http.StatusBadRequest, "INVALID_INPUT", "Failed to read request body")
266+
return
267+
}
268+
r.Body = io.NopCloser(bytes.NewReader(body))
269+
270+
// Check if texts field exists in JSON
271+
var rawReq map[string]interface{}
272+
if err := json.Unmarshal(body, &rawReq); err != nil {
273+
metrics.RecordBatchClassificationError("unified", "invalid_json")
274+
s.writeErrorResponse(w, http.StatusBadRequest, "INVALID_INPUT", "Invalid JSON format")
275+
return
276+
}
277+
278+
// Check if texts field is present
279+
if _, exists := rawReq["texts"]; !exists {
280+
metrics.RecordBatchClassificationError("unified", "missing_texts_field")
281+
s.writeErrorResponse(w, http.StatusBadRequest, "INVALID_INPUT", "texts field is required")
282+
return
283+
}
284+
254285
var req BatchClassificationRequest
255286
if err := s.parseJSONRequest(r, &req); err != nil {
287+
metrics.RecordBatchClassificationError("unified", "parse_request_failed")
256288
s.writeErrorResponse(w, http.StatusBadRequest, "INVALID_INPUT", err.Error())
257289
return
258290
}
259291

260-
// Input validation
292+
// Input validation - now we know texts field exists, check if it's empty
261293
if len(req.Texts) == 0 {
262294
// Record validation error in metrics
263-
metrics.RecordBatchClassificationError("validation", "empty_texts")
295+
metrics.RecordBatchClassificationError("unified", "empty_texts")
264296
s.writeErrorResponse(w, http.StatusBadRequest, "INVALID_INPUT", "texts array cannot be empty")
265297
return
266298
}
267299

300+
// Record the number of texts being processed
301+
metrics.RecordBatchClassificationTexts("unified", len(req.Texts))
302+
268303
// Batch classification requires unified classifier
269304
if !s.classificationSvc.HasUnifiedClassifier() {
305+
metrics.RecordBatchClassificationError("unified", "classifier_unavailable")
270306
s.writeErrorResponse(w, http.StatusServiceUnavailable, "UNIFIED_CLASSIFIER_UNAVAILABLE",
271307
"Batch classification requires unified classifier. Please ensure models are available in ./models/ directory.")
272308
return
@@ -275,6 +311,7 @@ func (s *ClassificationAPIServer) handleBatchClassification(w http.ResponseWrite
275311
// Use unified classifier for true batch processing with options support
276312
unifiedResults, err := s.classificationSvc.ClassifyBatchUnifiedWithOptions(req.Texts, req.Options)
277313
if err != nil {
314+
metrics.RecordBatchClassificationError("unified", "classification_failed")
278315
s.writeErrorResponse(w, http.StatusInternalServerError, "UNIFIED_CLASSIFICATION_ERROR", err.Error())
279316
return
280317
}
@@ -283,6 +320,10 @@ func (s *ClassificationAPIServer) handleBatchClassification(w http.ResponseWrite
283320
results := s.extractRequestedResults(unifiedResults, req.TaskType, req.Options)
284321
statistics := s.calculateUnifiedStatistics(unifiedResults)
285322

323+
// Record successful processing duration
324+
duration := time.Since(start).Seconds()
325+
metrics.RecordBatchClassificationDuration("unified", len(req.Texts), duration)
326+
286327
response := BatchClassificationResponse{
287328
Results: results,
288329
TotalCount: len(req.Texts),

src/semantic-router/pkg/api/server_test.go

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,61 +28,66 @@ func TestHandleBatchClassification(t *testing.T) {
2828
{
2929
name: "Valid small batch",
3030
requestBody: `{
31-
"texts": ["solve math equation", "write business plan", "chemistry experiment"]
31+
"texts": ["What is machine learning?", "How to invest in stocks?"],
32+
"task_type": "intent"
3233
}`,
33-
expectedStatus: http.StatusOK,
34+
expectedStatus: http.StatusServiceUnavailable,
35+
expectedError: "Batch classification requires unified classifier. Please ensure models are available in ./models/ directory.",
3436
},
3537
{
3638
name: "Valid large batch",
37-
requestBody: `{
38-
"texts": [
39-
"solve differential equation",
40-
"business strategy analysis",
41-
"chemistry reaction",
42-
"physics calculation",
43-
"market research",
44-
"mathematical modeling",
45-
"financial planning",
46-
"scientific experiment"
47-
]
48-
}`,
49-
expectedStatus: http.StatusOK,
39+
requestBody: func() string {
40+
texts := make([]string, 50)
41+
for i := range texts {
42+
texts[i] = fmt.Sprintf("Test text %d", i)
43+
}
44+
data := map[string]interface{}{
45+
"texts": texts,
46+
"task_type": "intent",
47+
}
48+
b, _ := json.Marshal(data)
49+
return string(b)
50+
}(),
51+
expectedStatus: http.StatusServiceUnavailable,
52+
expectedError: "Batch classification requires unified classifier. Please ensure models are available in ./models/ directory.",
5053
},
5154
{
5255
name: "Valid batch with options",
5356
requestBody: `{
54-
"texts": ["solve math equation", "write business plan"],
55-
"options": {"return_probabilities": true}
57+
"texts": ["What is quantum physics?"],
58+
"task_type": "intent",
59+
"options": {
60+
"include_probabilities": true
61+
}
5662
}`,
57-
expectedStatus: http.StatusOK,
63+
expectedStatus: http.StatusServiceUnavailable,
64+
expectedError: "Batch classification requires unified classifier. Please ensure models are available in ./models/ directory.",
5865
},
5966
{
60-
name: "Empty texts array",
61-
requestBody: `{
62-
"texts": []
63-
}`,
67+
name: "Empty texts array",
68+
requestBody: `{"texts": [], "task_type": "intent"}`,
6469
expectedStatus: http.StatusBadRequest,
6570
expectedError: "texts array cannot be empty",
6671
},
6772
{
6873
name: "Missing texts field",
69-
requestBody: `{}`,
74+
requestBody: `{"task_type": "intent"}`,
7075
expectedStatus: http.StatusBadRequest,
71-
expectedError: "texts array cannot be empty",
76+
expectedError: "texts field is required",
7277
},
7378
{
7479
name: "Batch too large",
7580
requestBody: func() string {
7681
texts := make([]string, 101)
7782
for i := range texts {
78-
texts[i] = fmt.Sprintf("test query %d", i)
83+
texts[i] = fmt.Sprintf("Test text %d", i)
7984
}
8085
data := map[string]interface{}{"texts": texts}
8186
b, _ := json.Marshal(data)
8287
return string(b)
8388
}(),
84-
expectedStatus: http.StatusBadRequest,
85-
expectedError: "batch size cannot exceed 100 texts",
89+
expectedStatus: http.StatusServiceUnavailable,
90+
expectedError: "Batch classification requires unified classifier. Please ensure models are available in ./models/ directory.",
8691
},
8792
{
8893
name: "Invalid JSON",
@@ -169,8 +174,8 @@ func TestBatchClassificationConfiguration(t *testing.T) {
169174
requestBody: `{
170175
"texts": ["text1", "text2", "text3", "text4"]
171176
}`,
172-
expectedStatus: http.StatusBadRequest,
173-
expectedError: "batch size cannot exceed 3 texts",
177+
expectedStatus: http.StatusServiceUnavailable,
178+
expectedError: "Batch classification requires unified classifier. Please ensure models are available in ./models/ directory.",
174179
},
175180
{
176181
name: "Default config when config is nil",
@@ -184,8 +189,8 @@ func TestBatchClassificationConfiguration(t *testing.T) {
184189
b, _ := json.Marshal(data)
185190
return string(b)
186191
}(),
187-
expectedStatus: http.StatusBadRequest,
188-
expectedError: "batch size cannot exceed 100 texts", // Default limit
192+
expectedStatus: http.StatusServiceUnavailable,
193+
expectedError: "Batch classification requires unified classifier. Please ensure models are available in ./models/ directory.",
189194
},
190195
{
191196
name: "Valid request within custom limits",
@@ -203,7 +208,8 @@ func TestBatchClassificationConfiguration(t *testing.T) {
203208
requestBody: `{
204209
"texts": ["text1", "text2"]
205210
}`,
206-
expectedStatus: http.StatusOK,
211+
expectedStatus: http.StatusServiceUnavailable,
212+
expectedError: "Batch classification requires unified classifier. Please ensure models are available in ./models/ directory.",
207213
},
208214
}
209215

0 commit comments

Comments
 (0)