first commit
This commit is contained in:
563
core/internal/mcptests/tool_conflicts_test.go
Normal file
563
core/internal/mcptests/tool_conflicts_test.go
Normal file
@@ -0,0 +1,563 @@
|
||||
package mcptests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/maximhq/bifrost/core/schemas"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// =============================================================================
|
||||
// TOOL NAME CONFLICT TESTS
|
||||
// =============================================================================
|
||||
|
||||
// TestToolNameConflict_MultipleClients - FULLY IMPLEMENTED EXAMPLE
|
||||
func TestToolNameConflict_MultipleClients(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
config := GetTestConfig(t)
|
||||
if config.HTTPServerURL == "" {
|
||||
t.Skip("MCP_HTTP_URL not set")
|
||||
}
|
||||
|
||||
// Create two clients with same tool
|
||||
client1Config := GetSampleHTTPClientConfig(config.HTTPServerURL)
|
||||
client1Config.ID = "client-1"
|
||||
client1Config.Name = "Client 1"
|
||||
|
||||
client2Config := GetSampleHTTPClientConfig(config.HTTPServerURL)
|
||||
client2Config.ID = "client-2"
|
||||
client2Config.Name = "Client 2"
|
||||
|
||||
manager := setupMCPManager(t, client1Config, client2Config)
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
// Execute a tool that exists on both clients
|
||||
ctx := createTestContext()
|
||||
toolCall := GetSampleEchoToolCall("call-1", "test")
|
||||
|
||||
result, bifrostErr := bifrost.ExecuteChatMCPTool(ctx, &toolCall)
|
||||
|
||||
// Should succeed (picks one of the clients)
|
||||
if bifrostErr == nil {
|
||||
t.Logf("Tool executed successfully, picked client: %v", result)
|
||||
// Check ExtraFields to see which client was selected
|
||||
} else {
|
||||
t.Logf("Tool execution failed: %v", bifrostErr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolNameConflict_Resolution(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Setup in-process client
|
||||
clientConfig := GetSampleInProcessClientConfig()
|
||||
clientConfig.ToolsToExecute = []string{"*"}
|
||||
|
||||
manager := setupMCPManager(t, clientConfig)
|
||||
|
||||
// Register echo tool - will be available as bifrostInternal-echo
|
||||
require.NoError(t, RegisterEchoTool(manager))
|
||||
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
ctx := createTestContext()
|
||||
|
||||
// Execute "echo" tool multiple times to verify consistent execution
|
||||
for i := 0; i < 10; i++ {
|
||||
toolCall := GetSampleEchoToolCall("call-"+string(rune(i)), "test conflict resolution")
|
||||
result, bifrostErr := bifrost.ExecuteChatMCPTool(ctx, &toolCall)
|
||||
require.Nil(t, bifrostErr, "tool should execute")
|
||||
require.NotNil(t, result)
|
||||
t.Logf("Execution %d completed", i+1)
|
||||
}
|
||||
|
||||
t.Log("✓ Tool executed consistently across multiple calls")
|
||||
}
|
||||
|
||||
func TestToolNameConflict_WithFiltering(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
config := GetTestConfig(t)
|
||||
if config.HTTPServerURL == "" || config.SSEServerURL == "" {
|
||||
t.Skip("MCP_HTTP_SERVER_URL or MCP_SSE_URL not set")
|
||||
}
|
||||
|
||||
// Client 1: has "echo" tool, ToolsToExecute = ["echo"]
|
||||
client1 := GetSampleHTTPClientConfig(config.HTTPServerURL)
|
||||
client1.ID = "http-allow-echo"
|
||||
client1.ToolsToExecute = []string{"echo"}
|
||||
|
||||
// Client 2: has "echo" tool, ToolsToExecute = [] (deny all)
|
||||
client2 := GetSampleSSEClientConfig(config.SSEServerURL)
|
||||
client2.ID = "sse-deny-all"
|
||||
client2.ToolsToExecute = []string{} // Deny all
|
||||
|
||||
manager := setupMCPManager(t, client1, client2)
|
||||
// Register the echo tool for bifrostInternal
|
||||
require.NoError(t, RegisterEchoTool(manager))
|
||||
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
ctx := createTestContext()
|
||||
|
||||
// Execute "echo" - should use bifrostInternal client (it's the only one with the tool registered in-process)
|
||||
toolCall := GetSampleEchoToolCall("call-1", "filtered conflict")
|
||||
result, bifrostErr := bifrost.ExecuteChatMCPTool(ctx, &toolCall)
|
||||
err := bifrostErr
|
||||
require.Nil(t, err, "should execute echo tool")
|
||||
require.NotNil(t, result)
|
||||
|
||||
// Verify it executed successfully
|
||||
// Note: ExecuteChatMCPTool doesn't return ExtraFields, so we can't verify client name
|
||||
// The tool execution succeeded, which is what we're testing
|
||||
}
|
||||
|
||||
func TestToolNameConflict_LocalVsExternal(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
config := GetTestConfig(t)
|
||||
if config.HTTPServerURL == "" {
|
||||
t.Skip("MCP_HTTP_URL not set")
|
||||
}
|
||||
|
||||
// Create HTTP client with "echo" tool (external)
|
||||
httpClient := GetSampleHTTPClientConfig(config.HTTPServerURL)
|
||||
httpClient.ID = "http-external"
|
||||
httpClient.ToolsToExecute = []string{"*"}
|
||||
|
||||
// Create InProcess client and will register "echo" tool (local)
|
||||
inProcessClient := GetSampleInProcessClientConfig()
|
||||
inProcessClient.ID = "inprocess-local"
|
||||
inProcessClient.ToolsToExecute = []string{"*"}
|
||||
|
||||
manager := setupMCPManager(t, httpClient, inProcessClient)
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
// Register "echo" tool in InProcess client
|
||||
echoTool := GetSampleEchoTool()
|
||||
echoToolHandler := func(args any) (string, error) {
|
||||
argsMap, ok := args.(map[string]interface{})
|
||||
if !ok {
|
||||
return "", fmt.Errorf("invalid arguments type")
|
||||
}
|
||||
message, ok := argsMap["message"].(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("message is required")
|
||||
}
|
||||
return message, nil
|
||||
}
|
||||
|
||||
err := manager.RegisterTool("echo", "Local echo tool", echoToolHandler, echoTool)
|
||||
require.NoError(t, err, "should register local echo tool")
|
||||
|
||||
ctx := createTestContext()
|
||||
|
||||
// Execute "echo" - verify which takes priority
|
||||
toolCall := GetSampleEchoToolCall("call-1", "local vs external")
|
||||
result, bifrostErr := bifrost.ExecuteChatMCPTool(ctx, &toolCall)
|
||||
require.Nil(t, bifrostErr, "tool should execute")
|
||||
require.NotNil(t, result)
|
||||
|
||||
// Check which client was used
|
||||
// Note: ExecuteChatMCPTool doesn't return ExtraFields, so we can't get client name
|
||||
t.Logf("Tool execution completed")
|
||||
// Priority behavior cannot be verified without ExtraFields
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// MULTIPLE SAME-NAME TOOLS TESTS
|
||||
// =============================================================================
|
||||
|
||||
func TestMultipleSameNameTools_ThreeClients(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create in-process client with "calculator" tool
|
||||
client := GetSampleInProcessClientConfig()
|
||||
client.ToolsToExecute = []string{"*"}
|
||||
|
||||
manager := setupMCPManager(t, client)
|
||||
|
||||
// Register calculator tool - will be available as bifrostInternal-calculator
|
||||
require.NoError(t, RegisterCalculatorTool(manager))
|
||||
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
ctx := createTestContext()
|
||||
|
||||
// Execute calculator multiple times
|
||||
for i := 0; i < 15; i++ {
|
||||
toolCall := GetSampleCalculatorToolCall("call-"+string(rune(i)), "add", float64(i), 1.0)
|
||||
result, bifrostErr := bifrost.ExecuteChatMCPTool(ctx, &toolCall)
|
||||
require.Nil(t, bifrostErr, "calculator should execute")
|
||||
require.NotNil(t, result)
|
||||
}
|
||||
|
||||
// Verify only the bifrostInternal client is active (disconnected clients may be
|
||||
// retained in memory for auto-recovery and should not be counted here)
|
||||
clients := manager.GetClients()
|
||||
activeClients := 0
|
||||
for _, c := range clients {
|
||||
if c.State != schemas.MCPConnectionStateDisconnected {
|
||||
activeClients++
|
||||
}
|
||||
}
|
||||
assert.Equal(t, 1, activeClients, "should have 1 bifrostInternal client")
|
||||
t.Log("✓ Calculator executed successfully across 15 calls")
|
||||
}
|
||||
|
||||
func TestMultipleSameNameTools_DifferentImplementations(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Use bifrostInternal client only with registered tools
|
||||
inProcessClient := GetSampleInProcessClientConfig()
|
||||
inProcessClient.ID = "inprocess-custom"
|
||||
inProcessClient.ToolsToExecute = []string{"*"}
|
||||
|
||||
manager := setupMCPManager(t, inProcessClient)
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
// Register custom "process_data" tool in InProcess client
|
||||
processTool := schemas.ChatTool{
|
||||
Type: schemas.ChatToolTypeFunction,
|
||||
Function: &schemas.ChatToolFunction{
|
||||
Name: "process_data",
|
||||
Description: schemas.Ptr("Custom data processor"),
|
||||
Parameters: &schemas.ToolFunctionParameters{
|
||||
Type: "object",
|
||||
Properties: schemas.NewOrderedMapFromPairs(
|
||||
schemas.KV("data", map[string]interface{}{
|
||||
"type": "string",
|
||||
"description": "Data to process",
|
||||
}),
|
||||
),
|
||||
Required: []string{"data"},
|
||||
},
|
||||
},
|
||||
}
|
||||
processToolHandler := func(args any) (string, error) {
|
||||
argsMap, ok := args.(map[string]interface{})
|
||||
if !ok {
|
||||
return "", fmt.Errorf("invalid arguments type")
|
||||
}
|
||||
data, ok := argsMap["data"].(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("data is required")
|
||||
}
|
||||
return "Processed: " + data, nil
|
||||
}
|
||||
|
||||
err := manager.RegisterTool("process_data", "Custom data processor", processToolHandler, processTool)
|
||||
require.Nil(t, err)
|
||||
|
||||
ctx := createTestContext()
|
||||
|
||||
// Execute "process_data" tool multiple times
|
||||
for i := 0; i < 5; i++ {
|
||||
toolCall := schemas.ChatAssistantMessageToolCall{
|
||||
ID: schemas.Ptr("call-" + string(rune(i))),
|
||||
Type: schemas.Ptr("function"),
|
||||
Function: schemas.ChatAssistantMessageToolCallFunction{
|
||||
Name: schemas.Ptr("bifrostInternal-process_data"),
|
||||
Arguments: `{"data": "test"}`,
|
||||
},
|
||||
}
|
||||
|
||||
result, bifrostErr := bifrost.ExecuteChatMCPTool(ctx, &toolCall)
|
||||
require.Nil(t, bifrostErr, "process_data should execute")
|
||||
require.NotNil(t, result)
|
||||
}
|
||||
|
||||
t.Log("✓ Custom tool execution completed successfully")
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// CONFLICT WITH CLIENT STATES
|
||||
// =============================================================================
|
||||
|
||||
func TestToolConflict_OneClientDisconnected(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Client 1: connected in-process client
|
||||
client1 := GetSampleInProcessClientConfig()
|
||||
client1.ID = "connected-client"
|
||||
client1.ToolsToExecute = []string{"*"}
|
||||
|
||||
// Client 2: disconnected (bad config to simulate disconnect)
|
||||
client2 := GetSampleHTTPClientConfig("http://localhost:1")
|
||||
client2.ID = "disconnected-client"
|
||||
client2.ToolsToExecute = []string{"*"}
|
||||
|
||||
manager := setupMCPManager(t, client1, client2)
|
||||
|
||||
// Register echo tool - will be available as bifrostInternal-echo on client1
|
||||
require.NoError(t, RegisterEchoTool(manager))
|
||||
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
// Wait a bit for client2 to fail connection
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Verify only bifrostInternal is active (disconnected clients may be retained
|
||||
// in memory for auto-recovery but should not be counted as active)
|
||||
clients := manager.GetClients()
|
||||
activeClients := 0
|
||||
for _, c := range clients {
|
||||
if c.State != schemas.MCPConnectionStateDisconnected {
|
||||
activeClients++
|
||||
}
|
||||
}
|
||||
require.Equal(t, 1, activeClients, "should only have 1 active client (bifrostInternal)")
|
||||
|
||||
ctx := createTestContext()
|
||||
|
||||
// Execute "echo" - should use Client 1 (only connected one)
|
||||
toolCall := GetSampleEchoToolCall("call-1", "disconnected conflict")
|
||||
result, bifrostErr := bifrost.ExecuteChatMCPTool(ctx, &toolCall)
|
||||
require.Nil(t, bifrostErr, "should use connected client")
|
||||
require.NotNil(t, result)
|
||||
t.Log("✓ Tool executed successfully using the connected client")
|
||||
}
|
||||
|
||||
func TestToolConflict_BothClientsDisconnected(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Both clients have "echo" but both are disconnected
|
||||
// Using bad URLs to force disconnect
|
||||
client1 := GetSampleHTTPClientConfig("http://localhost:1")
|
||||
client1.ID = "disconnected-1"
|
||||
client1.ToolsToExecute = []string{"*"}
|
||||
|
||||
client2 := GetSampleHTTPClientConfig("http://localhost:2")
|
||||
client2.ID = "disconnected-2"
|
||||
client2.ToolsToExecute = []string{"*"}
|
||||
|
||||
manager := setupMCPManager(t, client1, client2)
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
// Wait for both to fail connection
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Verify both are disconnected
|
||||
clients := manager.GetClients()
|
||||
for _, client := range clients {
|
||||
t.Logf("Client %s state: %v", client.ExecutionConfig.ID, client.State)
|
||||
}
|
||||
|
||||
ctx := createTestContext()
|
||||
|
||||
// Execute "echo" - should return error (no available client)
|
||||
toolCall := GetSampleEchoToolCall("call-1", "all disconnected")
|
||||
result, bifrostErr := bifrost.ExecuteChatMCPTool(ctx, &toolCall)
|
||||
|
||||
// Should fail because no client is available
|
||||
assert.NotNil(t, bifrostErr, "should fail when all clients are disconnected")
|
||||
assert.Nil(t, result)
|
||||
if bifrostErr != nil && bifrostErr.Error != nil {
|
||||
errorMsg := bifrostErr.Error.Message
|
||||
// Error message can be "not found", "not available", or "not permitted"
|
||||
hasExpectedError := assert.True(t,
|
||||
strings.Contains(errorMsg, "not available") || strings.Contains(errorMsg, "not permitted") || strings.Contains(errorMsg, "not found"),
|
||||
"error should mention tool is not available/permitted/found, got: %s", errorMsg)
|
||||
_ = hasExpectedError
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// BOTH API FORMATS CONFLICT TESTS
|
||||
// =============================================================================
|
||||
|
||||
func TestToolConflict_ChatFormat(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Use bifrostInternal clients with registered tools
|
||||
inProcessClient := GetSampleInProcessClientConfig()
|
||||
inProcessClient.ID = "inprocess-client"
|
||||
inProcessClient.ToolsToExecute = []string{"*"}
|
||||
|
||||
manager := setupMCPManager(t, inProcessClient)
|
||||
|
||||
// Register all tools needed for this test
|
||||
require.NoError(t, RegisterEchoTool(manager))
|
||||
require.NoError(t, RegisterCalculatorTool(manager))
|
||||
require.NoError(t, RegisterWeatherTool(manager))
|
||||
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
ctx := createTestContext()
|
||||
|
||||
// Execute in Chat format
|
||||
testCases := []struct {
|
||||
name string
|
||||
toolCall schemas.ChatAssistantMessageToolCall
|
||||
}{
|
||||
{
|
||||
name: "echo_tool",
|
||||
toolCall: GetSampleEchoToolCall("call-echo", "chat format conflict"),
|
||||
},
|
||||
{
|
||||
name: "calculator_tool",
|
||||
toolCall: GetSampleCalculatorToolCall("call-calc", "multiply", 7, 8),
|
||||
},
|
||||
{
|
||||
name: "weather_tool",
|
||||
toolCall: GetSampleWeatherToolCall("call-weather", "London", ""),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result, bifrostErr := bifrost.ExecuteChatMCPTool(ctx, &tc.toolCall)
|
||||
if bifrostErr != nil && bifrostErr.Error != nil {
|
||||
fmt.Println("bifrostErr", bifrostErr.Error.Message)
|
||||
}
|
||||
require.Nil(t, bifrostErr, "should resolve conflict and execute")
|
||||
require.NotNil(t, result)
|
||||
|
||||
// Log which client was selected
|
||||
// Note: ExecuteChatMCPTool doesn't return ExtraFields
|
||||
t.Logf("Tool %s executed successfully", *tc.toolCall.Function.Name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolConflict_ResponsesFormat(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Use bifrostInternal clients with registered tools
|
||||
inProcessClient := GetSampleInProcessClientConfig()
|
||||
inProcessClient.ID = "inprocess-client"
|
||||
inProcessClient.ToolsToExecute = []string{"*"}
|
||||
|
||||
manager := setupMCPManager(t, inProcessClient)
|
||||
|
||||
// Register all tools needed for this test
|
||||
require.NoError(t, RegisterEchoTool(manager))
|
||||
require.NoError(t, RegisterCalculatorTool(manager))
|
||||
require.NoError(t, RegisterWeatherTool(manager))
|
||||
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
ctx := createTestContext()
|
||||
|
||||
// Execute in Responses format
|
||||
testCases := []struct {
|
||||
name string
|
||||
responsesToolMsg schemas.ResponsesToolMessage
|
||||
}{
|
||||
{
|
||||
name: "echo_tool",
|
||||
responsesToolMsg: schemas.ResponsesToolMessage{
|
||||
CallID: schemas.Ptr("call-echo"),
|
||||
Name: schemas.Ptr("bifrostInternal-echo"),
|
||||
Arguments: schemas.Ptr(`{"message": "responses format conflict"}`),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "calculator_tool",
|
||||
responsesToolMsg: schemas.ResponsesToolMessage{
|
||||
CallID: schemas.Ptr("call-calc"),
|
||||
Name: schemas.Ptr("bifrostInternal-calculator"),
|
||||
Arguments: schemas.Ptr(`{"operation": "add", "x": 15, "y": 25}`),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "weather_tool",
|
||||
responsesToolMsg: schemas.ResponsesToolMessage{
|
||||
CallID: schemas.Ptr("call-weather"),
|
||||
Name: schemas.Ptr("bifrostInternal-get_weather"),
|
||||
Arguments: schemas.Ptr(`{"location": "Tokyo"}`),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result, bifrostErr := bifrost.ExecuteResponsesMCPTool(ctx, &tc.responsesToolMsg)
|
||||
require.Nil(t, bifrostErr, "should resolve conflict and execute")
|
||||
require.NotNil(t, result)
|
||||
|
||||
// Log which client was selected
|
||||
// Note: ExecuteResponsesMCPTool doesn't return ExtraFields
|
||||
t.Logf("Tool %s executed successfully", *tc.responsesToolMsg.Name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// COMPREHENSIVE CONFLICT SCENARIOS
|
||||
// =============================================================================
|
||||
|
||||
func TestToolConflict_ComprehensiveScenarios(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Use bifrostInternal clients with registered tools
|
||||
inProcessClient := GetSampleInProcessClientConfig()
|
||||
inProcessClient.ID = "inprocess-client"
|
||||
inProcessClient.ToolsToExecute = []string{"*"}
|
||||
|
||||
manager := setupMCPManager(t, inProcessClient)
|
||||
|
||||
// Register all tools needed for this test
|
||||
require.NoError(t, RegisterEchoTool(manager))
|
||||
require.NoError(t, RegisterCalculatorTool(manager))
|
||||
require.NoError(t, RegisterWeatherTool(manager))
|
||||
|
||||
bifrost := setupBifrost(t)
|
||||
bifrost.SetMCPManager(manager)
|
||||
|
||||
ctx := createTestContext()
|
||||
|
||||
scenarios := []struct {
|
||||
name string
|
||||
toolName string
|
||||
expectSuccess bool
|
||||
}{
|
||||
{
|
||||
name: "echo_tool",
|
||||
toolName: "bifrostInternal-echo",
|
||||
expectSuccess: true,
|
||||
},
|
||||
{
|
||||
name: "calculator_tool",
|
||||
toolName: "bifrostInternal-calculator",
|
||||
expectSuccess: true,
|
||||
},
|
||||
{
|
||||
name: "weather_tool",
|
||||
toolName: "bifrostInternal-get_weather",
|
||||
expectSuccess: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
t.Run(scenario.name, func(t *testing.T) {
|
||||
toolCall := GetSampleEchoToolCall("call-"+scenario.toolName, "test")
|
||||
toolCall.Function.Name = schemas.Ptr(scenario.toolName)
|
||||
|
||||
result, bifrostErr := bifrost.ExecuteChatMCPTool(ctx, &toolCall)
|
||||
|
||||
if scenario.expectSuccess {
|
||||
require.Nil(t, bifrostErr, "should execute successfully")
|
||||
require.NotNil(t, result)
|
||||
t.Logf("Tool %s executed successfully", scenario.toolName)
|
||||
} else {
|
||||
assert.NotNil(t, bifrostErr, "should fail")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user