Files
onix/pkg/plugin/implementation/reqmapper/reqmapper_test.go
2025-12-05 16:09:02 +05:30

241 lines
5.9 KiB
Go

package reqmapper
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"reflect"
"sync"
"testing"
)
func resetEngineState(t *testing.T) {
t.Helper()
engineInstance = nil
engineOnce = sync.Once{}
}
func testMappingsFile(t *testing.T) string {
t.Helper()
path := filepath.Join("testdata", "mappings.yaml")
if _, err := os.Stat(path); err != nil {
t.Fatalf("test mappings file missing: %v", err)
}
return path
}
func initTestEngine(t *testing.T) *MappingEngine {
t.Helper()
resetEngineState(t)
engine, err := initMappingEngine(&Config{
Role: "bap",
MappingsFile: testMappingsFile(t),
})
if err != nil {
t.Fatalf("failed to init mapping engine: %v", err)
}
return engine
}
func TestNewReqMapper_InvalidConfig(t *testing.T) {
t.Run("nil config", func(t *testing.T) {
if _, err := NewReqMapper(nil); err == nil {
t.Fatalf("expected error for nil config")
}
})
t.Run("invalid role", func(t *testing.T) {
if _, err := NewReqMapper(&Config{Role: "invalid"}); err == nil {
t.Fatalf("expected error for invalid role")
}
})
}
func TestNewReqMapper_MiddlewareTransformsRequest(t *testing.T) {
resetEngineState(t)
mw, err := NewReqMapper(&Config{
Role: "bap",
MappingsFile: testMappingsFile(t),
})
if err != nil {
t.Fatalf("NewReqMapper returned error: %v", err)
}
startLocation := map[string]interface{}{
"gps": "12.9716,77.5946",
"city": "Bengaluru",
}
endLocation := map[string]interface{}{
"gps": "13.0827,80.2707",
"city": "Chennai",
}
requestPayload := map[string]interface{}{
"context": map[string]interface{}{
"domain": "retail",
"action": "search",
"version": "1.1.0",
"bap_id": "bap.example",
"bap_uri": "https://bap.example/api",
"transaction_id": "txn-1",
"message_id": "msg-1",
"timestamp": "2023-01-01T10:00:00Z",
},
"message": map[string]interface{}{
"intent": map[string]interface{}{
"item": map[string]interface{}{
"id": "item-1",
},
"provider": map[string]interface{}{
"id": "provider-1",
},
"fulfillment": map[string]interface{}{
"start": map[string]interface{}{
"location": startLocation,
},
"end": map[string]interface{}{
"location": endLocation,
},
},
},
},
}
body, err := json.Marshal(requestPayload)
if err != nil {
t.Fatalf("failed to marshal request payload: %v", err)
}
var captured map[string]interface{}
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
data, err := io.ReadAll(r.Body)
if err != nil {
t.Fatalf("failed to read request in handler: %v", err)
}
if err := json.Unmarshal(data, &captured); err != nil {
t.Fatalf("failed to unmarshal transformed payload: %v", err)
}
w.WriteHeader(http.StatusOK)
})
req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body))
rec := httptest.NewRecorder()
mw(next).ServeHTTP(rec, req)
if captured == nil {
t.Fatalf("middleware did not forward request to next handler")
}
message, ok := captured["message"].(map[string]interface{})
if !ok {
t.Fatalf("expected message field in transformed payload")
}
filters, ok := message["filters"].(map[string]interface{})
if !ok {
t.Fatalf("expected filters in transformed payload")
}
if pickup := filters["pickup"]; !reflect.DeepEqual(pickup, startLocation) {
t.Fatalf("pickup location mismatch\ngot: %#v\nwant: %#v", pickup, startLocation)
}
if drop := filters["drop"]; !reflect.DeepEqual(drop, endLocation) {
t.Fatalf("drop location mismatch\ngot: %#v\nwant: %#v", drop, endLocation)
}
}
func TestMappingEngine_TransformFallbackForUnknownAction(t *testing.T) {
engine := initTestEngine(t)
req := map[string]interface{}{
"context": map[string]interface{}{
"action": "unknown_action",
},
"message": map[string]interface{}{},
}
expected, err := json.Marshal(req)
if err != nil {
t.Fatalf("failed to marshal expected payload: %v", err)
}
result, err := engine.Transform(context.Background(), "unknown_action", req, "bap")
if err != nil {
t.Fatalf("Transform returned error: %v", err)
}
if !bytes.Equal(result, expected) {
t.Fatalf("expected Transform to return original payload")
}
}
func TestMappingEngine_TransformFallbackForUnknownRole(t *testing.T) {
engine := initTestEngine(t)
req := map[string]interface{}{
"context": map[string]interface{}{
"action": "search",
},
"message": map[string]interface{}{},
}
expected, err := json.Marshal(req)
if err != nil {
t.Fatalf("failed to marshal expected payload: %v", err)
}
result, err := engine.Transform(context.Background(), "search", req, "unknown-role")
if err != nil {
t.Fatalf("Transform returned error: %v", err)
}
if !bytes.Equal(result, expected) {
t.Fatalf("expected Transform to return original payload when role is unknown")
}
}
func TestMappingEngine_ReloadMappings(t *testing.T) {
engine := initTestEngine(t)
engine.mutex.RLock()
originalBAP := len(engine.bapMaps)
originalBPP := len(engine.bppMaps)
engine.mutex.RUnlock()
if originalBAP == 0 || originalBPP == 0 {
t.Fatalf("expected test mappings to be loaded")
}
engine.mutex.Lock()
for action := range engine.bapMaps {
delete(engine.bapMaps, action)
break
}
engine.mutex.Unlock()
engine.mutex.RLock()
if len(engine.bapMaps) == originalBAP {
engine.mutex.RUnlock()
t.Fatalf("expected BAP map to be altered before reload")
}
engine.mutex.RUnlock()
if err := engine.ReloadMappings(); err != nil {
t.Fatalf("ReloadMappings returned error: %v", err)
}
engine.mutex.RLock()
defer engine.mutex.RUnlock()
if len(engine.bapMaps) != originalBAP {
t.Fatalf("expected BAP mappings to be reloaded, got %d want %d", len(engine.bapMaps), originalBAP)
}
if len(engine.bppMaps) != originalBPP {
t.Fatalf("expected BPP mappings to be reloaded, got %d want %d", len(engine.bppMaps), originalBPP)
}
}