#
tokens: 12832/50000 1/59 files (page 4/5)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 4 of 5. Use http://codebase.md/razorpay/razorpay-mcp-server?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .cursor
│   └── rules
│       └── new-tool-from-docs.mdc
├── .cursorignore
├── .dockerignore
├── .github
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   └── feature_request.md
│   ├── pull_request_template.md
│   └── workflows
│       ├── assign.yml
│       ├── build.yml
│       ├── ci.yml
│       ├── docker-publish.yml
│       ├── lint.yml
│       └── release.yml
├── .gitignore
├── .golangci.yaml
├── .goreleaser.yaml
├── cmd
│   └── razorpay-mcp-server
│       ├── main.go
│       └── stdio.go
├── codecov.yml
├── CONTRIBUTING.md
├── Dockerfile
├── go.mod
├── go.sum
├── LICENSE
├── Makefile
├── pkg
│   ├── contextkey
│   │   └── context_key.go
│   ├── log
│   │   ├── config.go
│   │   ├── log.go
│   │   ├── slog_test.go
│   │   └── slog.go
│   ├── mcpgo
│   │   ├── README.md
│   │   ├── server.go
│   │   ├── stdio.go
│   │   ├── tool.go
│   │   └── transport.go
│   ├── observability
│   │   └── observability.go
│   ├── razorpay
│   │   ├── mock
│   │   │   ├── server_test.go
│   │   │   └── server.go
│   │   ├── orders_test.go
│   │   ├── orders.go
│   │   ├── payment_links_test.go
│   │   ├── payment_links.go
│   │   ├── payments_test.go
│   │   ├── payments.go
│   │   ├── payouts_test.go
│   │   ├── payouts.go
│   │   ├── qr_codes_test.go
│   │   ├── qr_codes.go
│   │   ├── README.md
│   │   ├── refunds_test.go
│   │   ├── refunds.go
│   │   ├── server.go
│   │   ├── settlements_test.go
│   │   ├── settlements.go
│   │   ├── test_helpers.go
│   │   ├── tokens_test.go
│   │   ├── tokens.go
│   │   ├── tools_params_test.go
│   │   ├── tools_params.go
│   │   ├── tools_test.go
│   │   └── tools.go
│   └── toolsets
│       └── toolsets.go
├── README.md
└── SECURITY.md
```

# Files

--------------------------------------------------------------------------------
/pkg/razorpay/tools_params_test.go:
--------------------------------------------------------------------------------

```go
   1 | package razorpay
   2 | 
   3 | import (
   4 | 	"testing"
   5 | 
   6 | 	"github.com/stretchr/testify/assert"
   7 | 
   8 | 	"github.com/razorpay/razorpay-mcp-server/pkg/mcpgo"
   9 | )
  10 | 
  11 | func TestValidator(t *testing.T) {
  12 | 	tests := []struct {
  13 | 		name           string
  14 | 		args           map[string]interface{}
  15 | 		paramName      string
  16 | 		validationFunc func(*Validator, map[string]interface{}, string) *Validator
  17 | 		expectError    bool
  18 | 		expectValue    interface{}
  19 | 		expectKey      string
  20 | 	}{
  21 | 		// String tests
  22 | 		{
  23 | 			name:           "required string - valid",
  24 | 			args:           map[string]interface{}{"test_param": "test_value"},
  25 | 			paramName:      "test_param",
  26 | 			validationFunc: (*Validator).ValidateAndAddRequiredString,
  27 | 			expectError:    false,
  28 | 			expectValue:    "test_value",
  29 | 			expectKey:      "test_param",
  30 | 		},
  31 | 		{
  32 | 			name:           "required string - missing",
  33 | 			args:           map[string]interface{}{},
  34 | 			paramName:      "test_param",
  35 | 			validationFunc: (*Validator).ValidateAndAddRequiredString,
  36 | 			expectError:    true,
  37 | 			expectValue:    nil,
  38 | 			expectKey:      "test_param",
  39 | 		},
  40 | 		{
  41 | 			name:           "optional string - valid",
  42 | 			args:           map[string]interface{}{"test_param": "test_value"},
  43 | 			paramName:      "test_param",
  44 | 			validationFunc: (*Validator).ValidateAndAddOptionalString,
  45 | 			expectError:    false,
  46 | 			expectValue:    "test_value",
  47 | 			expectKey:      "test_param",
  48 | 		},
  49 | 		{
  50 | 			name:           "optional string - empty",
  51 | 			args:           map[string]interface{}{"test_param": ""},
  52 | 			paramName:      "test_param",
  53 | 			validationFunc: (*Validator).ValidateAndAddOptionalString,
  54 | 			expectError:    false,
  55 | 			expectValue:    "",
  56 | 			expectKey:      "test_param",
  57 | 		},
  58 | 
  59 | 		// Int tests
  60 | 		{
  61 | 			name:           "required int - valid",
  62 | 			args:           map[string]interface{}{"test_param": float64(123)},
  63 | 			paramName:      "test_param",
  64 | 			validationFunc: (*Validator).ValidateAndAddRequiredInt,
  65 | 			expectError:    false,
  66 | 			expectValue:    int64(123),
  67 | 			expectKey:      "test_param",
  68 | 		},
  69 | 		{
  70 | 			name:           "optional int - valid",
  71 | 			args:           map[string]interface{}{"test_param": float64(123)},
  72 | 			paramName:      "test_param",
  73 | 			validationFunc: (*Validator).ValidateAndAddOptionalInt,
  74 | 			expectError:    false,
  75 | 			expectValue:    int64(123),
  76 | 			expectKey:      "test_param",
  77 | 		},
  78 | 		{
  79 | 			name:           "optional int - zero",
  80 | 			args:           map[string]interface{}{"test_param": float64(0)},
  81 | 			paramName:      "test_param",
  82 | 			validationFunc: (*Validator).ValidateAndAddOptionalInt,
  83 | 			expectError:    false,
  84 | 			expectValue:    int64(0), // we expect the zero values as is
  85 | 			expectKey:      "test_param",
  86 | 		},
  87 | 
  88 | 		// Float tests
  89 | 		{
  90 | 			name:           "required float - valid",
  91 | 			args:           map[string]interface{}{"test_param": float64(123.45)},
  92 | 			paramName:      "test_param",
  93 | 			validationFunc: (*Validator).ValidateAndAddRequiredFloat,
  94 | 			expectError:    false,
  95 | 			expectValue:    float64(123.45),
  96 | 			expectKey:      "test_param",
  97 | 		},
  98 | 		{
  99 | 			name:           "optional float - valid",
 100 | 			args:           map[string]interface{}{"test_param": float64(123.45)},
 101 | 			paramName:      "test_param",
 102 | 			validationFunc: (*Validator).ValidateAndAddOptionalFloat,
 103 | 			expectError:    false,
 104 | 			expectValue:    float64(123.45),
 105 | 			expectKey:      "test_param",
 106 | 		},
 107 | 		{
 108 | 			name:           "optional float - zero",
 109 | 			args:           map[string]interface{}{"test_param": float64(0)},
 110 | 			paramName:      "test_param",
 111 | 			validationFunc: (*Validator).ValidateAndAddOptionalFloat,
 112 | 			expectError:    false,
 113 | 			expectValue:    float64(0),
 114 | 			expectKey:      "test_param",
 115 | 		},
 116 | 
 117 | 		// Bool tests
 118 | 		{
 119 | 			name:           "required bool - true",
 120 | 			args:           map[string]interface{}{"test_param": true},
 121 | 			paramName:      "test_param",
 122 | 			validationFunc: (*Validator).ValidateAndAddRequiredBool,
 123 | 			expectError:    false,
 124 | 			expectValue:    true,
 125 | 			expectKey:      "test_param",
 126 | 		},
 127 | 		{
 128 | 			name:           "required bool - false",
 129 | 			args:           map[string]interface{}{"test_param": false},
 130 | 			paramName:      "test_param",
 131 | 			validationFunc: (*Validator).ValidateAndAddRequiredBool,
 132 | 			expectError:    false,
 133 | 			expectValue:    false,
 134 | 			expectKey:      "test_param",
 135 | 		},
 136 | 		{
 137 | 			name:           "optional bool - true",
 138 | 			args:           map[string]interface{}{"test_param": true},
 139 | 			paramName:      "test_param",
 140 | 			validationFunc: (*Validator).ValidateAndAddOptionalBool,
 141 | 			expectError:    false,
 142 | 			expectValue:    true,
 143 | 			expectKey:      "test_param",
 144 | 		},
 145 | 		{
 146 | 			name:           "optional bool - false",
 147 | 			args:           map[string]interface{}{"test_param": false},
 148 | 			paramName:      "test_param",
 149 | 			validationFunc: (*Validator).ValidateAndAddOptionalBool,
 150 | 			expectError:    false,
 151 | 			expectValue:    false,
 152 | 			expectKey:      "test_param",
 153 | 		},
 154 | 
 155 | 		// Map tests
 156 | 		{
 157 | 			name: "required map - valid",
 158 | 			args: map[string]interface{}{
 159 | 				"test_param": map[string]interface{}{"key": "value"},
 160 | 			},
 161 | 			paramName:      "test_param",
 162 | 			validationFunc: (*Validator).ValidateAndAddRequiredMap,
 163 | 			expectError:    false,
 164 | 			expectValue:    map[string]interface{}{"key": "value"},
 165 | 			expectKey:      "test_param",
 166 | 		},
 167 | 		{
 168 | 			name: "optional map - valid",
 169 | 			args: map[string]interface{}{
 170 | 				"test_param": map[string]interface{}{"key": "value"},
 171 | 			},
 172 | 			paramName:      "test_param",
 173 | 			validationFunc: (*Validator).ValidateAndAddOptionalMap,
 174 | 			expectError:    false,
 175 | 			expectValue:    map[string]interface{}{"key": "value"},
 176 | 			expectKey:      "test_param",
 177 | 		},
 178 | 		{
 179 | 			name: "optional map - empty",
 180 | 			args: map[string]interface{}{
 181 | 				"test_param": map[string]interface{}{},
 182 | 			},
 183 | 			paramName:      "test_param",
 184 | 			validationFunc: (*Validator).ValidateAndAddOptionalMap,
 185 | 			expectError:    false,
 186 | 			expectValue:    map[string]interface{}{},
 187 | 			expectKey:      "test_param",
 188 | 		},
 189 | 
 190 | 		// Array tests
 191 | 		{
 192 | 			name: "required array - valid",
 193 | 			args: map[string]interface{}{
 194 | 				"test_param": []interface{}{"value1", "value2"},
 195 | 			},
 196 | 			paramName:      "test_param",
 197 | 			validationFunc: (*Validator).ValidateAndAddRequiredArray,
 198 | 			expectError:    false,
 199 | 			expectValue:    []interface{}{"value1", "value2"},
 200 | 			expectKey:      "test_param",
 201 | 		},
 202 | 		{
 203 | 			name: "optional array - valid",
 204 | 			args: map[string]interface{}{
 205 | 				"test_param": []interface{}{"value1", "value2"},
 206 | 			},
 207 | 			paramName:      "test_param",
 208 | 			validationFunc: (*Validator).ValidateAndAddOptionalArray,
 209 | 			expectError:    false,
 210 | 			expectValue:    []interface{}{"value1", "value2"},
 211 | 			expectKey:      "test_param",
 212 | 		},
 213 | 		{
 214 | 			name:           "optional array - empty",
 215 | 			args:           map[string]interface{}{"test_param": []interface{}{}},
 216 | 			paramName:      "test_param",
 217 | 			validationFunc: (*Validator).ValidateAndAddOptionalArray,
 218 | 			expectError:    false,
 219 | 			expectValue:    []interface{}{},
 220 | 			expectKey:      "test_param",
 221 | 		},
 222 | 
 223 | 		// Invalid type tests
 224 | 		{
 225 | 			name:           "required string - wrong type",
 226 | 			args:           map[string]interface{}{"test_param": 123},
 227 | 			paramName:      "test_param",
 228 | 			validationFunc: (*Validator).ValidateAndAddRequiredString,
 229 | 			expectError:    true,
 230 | 			expectValue:    nil,
 231 | 			expectKey:      "test_param",
 232 | 		},
 233 | 		{
 234 | 			name:           "required int - wrong type",
 235 | 			args:           map[string]interface{}{"test_param": "not a number"},
 236 | 			paramName:      "test_param",
 237 | 			validationFunc: (*Validator).ValidateAndAddRequiredInt,
 238 | 			expectError:    true,
 239 | 			expectValue:    nil,
 240 | 			expectKey:      "test_param",
 241 | 		},
 242 | 	}
 243 | 
 244 | 	for _, tt := range tests {
 245 | 		t.Run(tt.name, func(t *testing.T) {
 246 | 			result := make(map[string]interface{})
 247 | 			request := &mcpgo.CallToolRequest{
 248 | 				Arguments: tt.args,
 249 | 			}
 250 | 			validator := NewValidator(request)
 251 | 
 252 | 			tt.validationFunc(validator, result, tt.paramName)
 253 | 
 254 | 			if tt.expectError {
 255 | 				assert.True(t, validator.HasErrors(), "Expected validation error")
 256 | 			} else {
 257 | 				assert.False(t, validator.HasErrors(), "Did not expect validation error")
 258 | 				assert.Equal(t,
 259 | 					tt.expectValue,
 260 | 					result[tt.expectKey],
 261 | 					"Parameter value mismatch",
 262 | 				)
 263 | 			}
 264 | 		})
 265 | 	}
 266 | }
 267 | 
 268 | func TestValidatorPagination(t *testing.T) {
 269 | 	tests := []struct {
 270 | 		name        string
 271 | 		args        map[string]interface{}
 272 | 		expectCount interface{}
 273 | 		expectSkip  interface{}
 274 | 		expectError bool
 275 | 	}{
 276 | 		{
 277 | 			name: "valid pagination params",
 278 | 			args: map[string]interface{}{
 279 | 				"count": float64(10),
 280 | 				"skip":  float64(5),
 281 | 			},
 282 | 			expectCount: int64(10),
 283 | 			expectSkip:  int64(5),
 284 | 			expectError: false,
 285 | 		},
 286 | 		{
 287 | 			name:        "zero pagination params",
 288 | 			args:        map[string]interface{}{"count": float64(0), "skip": float64(0)},
 289 | 			expectCount: int64(0),
 290 | 			expectSkip:  int64(0),
 291 | 			expectError: false,
 292 | 		},
 293 | 		{
 294 | 			name: "invalid count type",
 295 | 			args: map[string]interface{}{
 296 | 				"count": "not a number",
 297 | 				"skip":  float64(5),
 298 | 			},
 299 | 			expectCount: nil,
 300 | 			expectSkip:  int64(5),
 301 | 			expectError: true,
 302 | 		},
 303 | 	}
 304 | 
 305 | 	for _, tt := range tests {
 306 | 		t.Run(tt.name, func(t *testing.T) {
 307 | 			result := make(map[string]interface{})
 308 | 			request := &mcpgo.CallToolRequest{
 309 | 				Arguments: tt.args,
 310 | 			}
 311 | 			validator := NewValidator(request)
 312 | 
 313 | 			validator.ValidateAndAddPagination(result)
 314 | 
 315 | 			if tt.expectError {
 316 | 				assert.True(t, validator.HasErrors(), "Expected validation error")
 317 | 			} else {
 318 | 				assert.False(t, validator.HasErrors(), "Did not expect validation error")
 319 | 			}
 320 | 
 321 | 			if tt.expectCount != nil {
 322 | 				assert.Equal(t, tt.expectCount, result["count"], "Count mismatch")
 323 | 			} else {
 324 | 				_, exists := result["count"]
 325 | 				assert.False(t, exists, "Count should not be added")
 326 | 			}
 327 | 
 328 | 			if tt.expectSkip != nil {
 329 | 				assert.Equal(t, tt.expectSkip, result["skip"], "Skip mismatch")
 330 | 			} else {
 331 | 				_, exists := result["skip"]
 332 | 				assert.False(t, exists, "Skip should not be added")
 333 | 			}
 334 | 		})
 335 | 	}
 336 | }
 337 | 
 338 | func TestValidatorExpand(t *testing.T) {
 339 | 	tests := []struct {
 340 | 		name         string
 341 | 		args         map[string]interface{}
 342 | 		expectExpand string
 343 | 		expectError  bool
 344 | 	}{
 345 | 		{
 346 | 			name:         "valid expand param",
 347 | 			args:         map[string]interface{}{"expand": []interface{}{"payments"}},
 348 | 			expectExpand: "payments",
 349 | 			expectError:  false,
 350 | 		},
 351 | 		{
 352 | 			name:         "empty expand array",
 353 | 			args:         map[string]interface{}{"expand": []interface{}{}},
 354 | 			expectExpand: "",
 355 | 			expectError:  false,
 356 | 		},
 357 | 		{
 358 | 			name:         "invalid expand type",
 359 | 			args:         map[string]interface{}{"expand": "not an array"},
 360 | 			expectExpand: "",
 361 | 			expectError:  true,
 362 | 		},
 363 | 	}
 364 | 
 365 | 	for _, tt := range tests {
 366 | 		t.Run(tt.name, func(t *testing.T) {
 367 | 			result := make(map[string]interface{})
 368 | 			request := &mcpgo.CallToolRequest{
 369 | 				Arguments: tt.args,
 370 | 			}
 371 | 			validator := NewValidator(request)
 372 | 
 373 | 			validator.ValidateAndAddExpand(result)
 374 | 
 375 | 			if tt.expectError {
 376 | 				assert.True(t, validator.HasErrors(), "Expected validation error")
 377 | 			} else {
 378 | 				assert.False(t, validator.HasErrors(), "Did not expect validation error")
 379 | 				if tt.expectExpand != "" {
 380 | 					assert.Equal(t,
 381 | 						tt.expectExpand,
 382 | 						result["expand[]"],
 383 | 						"Expand value mismatch",
 384 | 					)
 385 | 				} else {
 386 | 					_, exists := result["expand[]"]
 387 | 					assert.False(t, exists, "Expand should not be added")
 388 | 				}
 389 | 			}
 390 | 		})
 391 | 	}
 392 | }
 393 | 
 394 | // Test validator "To" functions which write to target maps
 395 | func TestValidatorToFunctions(t *testing.T) {
 396 | 	tests := []struct {
 397 | 		name      string
 398 | 		args      map[string]interface{}
 399 | 		paramName string
 400 | 		targetKey string
 401 | 		testFunc  func(
 402 | 			*Validator, map[string]interface{}, string, string,
 403 | 		) *Validator
 404 | 		expectValue interface{}
 405 | 		expectError bool
 406 | 	}{
 407 | 		// ValidateAndAddOptionalStringToPath tests
 408 | 		{
 409 | 			name:        "optional string to target - valid",
 410 | 			args:        map[string]interface{}{"customer_name": "Test User"},
 411 | 			paramName:   "customer_name",
 412 | 			targetKey:   "name",
 413 | 			testFunc:    (*Validator).ValidateAndAddOptionalStringToPath,
 414 | 			expectValue: "Test User",
 415 | 			expectError: false,
 416 | 		},
 417 | 		{
 418 | 			name:        "optional string to target - empty",
 419 | 			args:        map[string]interface{}{"customer_name": ""},
 420 | 			paramName:   "customer_name",
 421 | 			targetKey:   "name",
 422 | 			testFunc:    (*Validator).ValidateAndAddOptionalStringToPath,
 423 | 			expectValue: "",
 424 | 			expectError: false,
 425 | 		},
 426 | 		{
 427 | 			name:        "optional string to target - missing",
 428 | 			args:        map[string]interface{}{},
 429 | 			paramName:   "customer_name",
 430 | 			targetKey:   "name",
 431 | 			testFunc:    (*Validator).ValidateAndAddOptionalStringToPath,
 432 | 			expectValue: nil,
 433 | 			expectError: false,
 434 | 		},
 435 | 		{
 436 | 			name:        "optional string to target - wrong type",
 437 | 			args:        map[string]interface{}{"customer_name": 123},
 438 | 			paramName:   "customer_name",
 439 | 			targetKey:   "name",
 440 | 			testFunc:    (*Validator).ValidateAndAddOptionalStringToPath,
 441 | 			expectValue: nil,
 442 | 			expectError: true,
 443 | 		},
 444 | 
 445 | 		// ValidateAndAddOptionalBoolToPath tests
 446 | 		{
 447 | 			name:        "optional bool to target - true",
 448 | 			args:        map[string]interface{}{"notify_sms": true},
 449 | 			paramName:   "notify_sms",
 450 | 			targetKey:   "sms",
 451 | 			testFunc:    (*Validator).ValidateAndAddOptionalBoolToPath,
 452 | 			expectValue: true,
 453 | 			expectError: false,
 454 | 		},
 455 | 		{
 456 | 			name:        "optional bool to target - false",
 457 | 			args:        map[string]interface{}{"notify_sms": false},
 458 | 			paramName:   "notify_sms",
 459 | 			targetKey:   "sms",
 460 | 			testFunc:    (*Validator).ValidateAndAddOptionalBoolToPath,
 461 | 			expectValue: false,
 462 | 			expectError: false,
 463 | 		},
 464 | 		{
 465 | 			name:        "optional bool to target - wrong type",
 466 | 			args:        map[string]interface{}{"notify_sms": "not a bool"},
 467 | 			paramName:   "notify_sms",
 468 | 			targetKey:   "sms",
 469 | 			testFunc:    (*Validator).ValidateAndAddOptionalBoolToPath,
 470 | 			expectValue: nil,
 471 | 			expectError: true,
 472 | 		},
 473 | 
 474 | 		// ValidateAndAddOptionalIntToPath tests
 475 | 		{
 476 | 			name:        "optional int to target - valid",
 477 | 			args:        map[string]interface{}{"age": float64(25)},
 478 | 			paramName:   "age",
 479 | 			targetKey:   "customer_age",
 480 | 			testFunc:    (*Validator).ValidateAndAddOptionalIntToPath,
 481 | 			expectValue: int64(25),
 482 | 			expectError: false,
 483 | 		},
 484 | 		{
 485 | 			name:        "optional int to target - zero",
 486 | 			args:        map[string]interface{}{"age": float64(0)},
 487 | 			paramName:   "age",
 488 | 			targetKey:   "customer_age",
 489 | 			testFunc:    (*Validator).ValidateAndAddOptionalIntToPath,
 490 | 			expectValue: int64(0),
 491 | 			expectError: false,
 492 | 		},
 493 | 		{
 494 | 			name:        "optional int to target - missing",
 495 | 			args:        map[string]interface{}{},
 496 | 			paramName:   "age",
 497 | 			targetKey:   "customer_age",
 498 | 			testFunc:    (*Validator).ValidateAndAddOptionalIntToPath,
 499 | 			expectValue: nil,
 500 | 			expectError: false,
 501 | 		},
 502 | 		{
 503 | 			name:        "optional int to target - wrong type",
 504 | 			args:        map[string]interface{}{"age": "not a number"},
 505 | 			paramName:   "age",
 506 | 			targetKey:   "customer_age",
 507 | 			testFunc:    (*Validator).ValidateAndAddOptionalIntToPath,
 508 | 			expectValue: nil,
 509 | 			expectError: true,
 510 | 		},
 511 | 	}
 512 | 
 513 | 	for _, tt := range tests {
 514 | 		t.Run(tt.name, func(t *testing.T) {
 515 | 			// Create a target map for this specific test
 516 | 			target := make(map[string]interface{})
 517 | 
 518 | 			// Create the request and validator
 519 | 			request := &mcpgo.CallToolRequest{
 520 | 				Arguments: tt.args,
 521 | 			}
 522 | 			validator := NewValidator(request)
 523 | 
 524 | 			// Call the test function with target and verify its return value
 525 | 			tt.testFunc(validator, target, tt.paramName, tt.targetKey)
 526 | 
 527 | 			// Check if we got the expected errors
 528 | 			if tt.expectError {
 529 | 				assert.True(t, validator.HasErrors(), "Expected validation error")
 530 | 			} else {
 531 | 				assert.False(t, validator.HasErrors(), "Did not expect validation error")
 532 | 
 533 | 				// For non-error cases, check target map value
 534 | 				if tt.expectValue != nil {
 535 | 					// Should have the value with the target key
 536 | 					assert.Equal(t,
 537 | 						tt.expectValue,
 538 | 						target[tt.targetKey],
 539 | 						"Target map value mismatch")
 540 | 				} else {
 541 | 					// Target key should not exist
 542 | 					_, exists := target[tt.targetKey]
 543 | 					assert.False(t, exists, "Key should not be in target map when value is empty") // nolint:lll
 544 | 				}
 545 | 			}
 546 | 		})
 547 | 	}
 548 | }
 549 | 
 550 | // Test for nested validation with multiple fields into target maps
 551 | func TestValidatorNestedObjects(t *testing.T) {
 552 | 	t.Run("customer object validation", func(t *testing.T) {
 553 | 		// Create request with customer details
 554 | 		args := map[string]interface{}{
 555 | 			"customer_name":    "John Doe",
 556 | 			"customer_email":   "[email protected]",
 557 | 			"customer_contact": "+1234567890",
 558 | 		}
 559 | 		request := &mcpgo.CallToolRequest{
 560 | 			Arguments: args,
 561 | 		}
 562 | 
 563 | 		// Customer target map
 564 | 		customer := make(map[string]interface{})
 565 | 
 566 | 		// Create validator and validate customer fields
 567 | 		validator := NewValidator(request).
 568 | 			ValidateAndAddOptionalStringToPath(customer, "customer_name", "name").
 569 | 			ValidateAndAddOptionalStringToPath(customer, "customer_email", "email").
 570 | 			ValidateAndAddOptionalStringToPath(customer, "customer_contact", "contact")
 571 | 
 572 | 		// Should not have errors
 573 | 		assert.False(t, validator.HasErrors())
 574 | 
 575 | 		// Customer map should have all three fields
 576 | 		assert.Equal(t, "John Doe", customer["name"])
 577 | 		assert.Equal(t, "[email protected]", customer["email"])
 578 | 		assert.Equal(t, "+1234567890", customer["contact"])
 579 | 	})
 580 | 
 581 | 	t.Run("notification object validation", func(t *testing.T) {
 582 | 		// Create request with notification settings
 583 | 		args := map[string]interface{}{
 584 | 			"notify_sms":   true,
 585 | 			"notify_email": false,
 586 | 		}
 587 | 		request := &mcpgo.CallToolRequest{
 588 | 			Arguments: args,
 589 | 		}
 590 | 
 591 | 		// Notify target map
 592 | 		notify := make(map[string]interface{})
 593 | 
 594 | 		// Create validator and validate notification fields
 595 | 		validator := NewValidator(request).
 596 | 			ValidateAndAddOptionalBoolToPath(notify, "notify_sms", "sms").
 597 | 			ValidateAndAddOptionalBoolToPath(notify, "notify_email", "email")
 598 | 
 599 | 		// Should not have errors
 600 | 		assert.False(t, validator.HasErrors())
 601 | 
 602 | 		// Notify map should have both fields
 603 | 		assert.Equal(t, true, notify["sms"])
 604 | 		assert.Equal(t, false, notify["email"])
 605 | 	})
 606 | 
 607 | 	t.Run("mixed object with error", func(t *testing.T) {
 608 | 		// Create request with mixed valid and invalid data
 609 | 		args := map[string]interface{}{
 610 | 			"customer_name":  "Jane Doe",
 611 | 			"customer_email": 12345, // Wrong type
 612 | 		}
 613 | 		request := &mcpgo.CallToolRequest{
 614 | 			Arguments: args,
 615 | 		}
 616 | 
 617 | 		// Target map
 618 | 		customer := make(map[string]interface{})
 619 | 
 620 | 		// Create validator and validate fields
 621 | 		validator := NewValidator(request).
 622 | 			ValidateAndAddOptionalStringToPath(customer, "customer_name", "name").
 623 | 			ValidateAndAddOptionalStringToPath(customer, "customer_email", "email")
 624 | 
 625 | 		// Should have errors
 626 | 		assert.True(t, validator.HasErrors())
 627 | 
 628 | 		// Customer map should have only the valid field
 629 | 		assert.Equal(t, "Jane Doe", customer["name"])
 630 | 		_, hasEmail := customer["email"]
 631 | 		assert.False(t, hasEmail, "Invalid field should not be added to target map")
 632 | 	})
 633 | }
 634 | 
 635 | // Test for optional bool handling
 636 | func TestOptionalBoolBehavior(t *testing.T) {
 637 | 	t.Run("explicit bool values", func(t *testing.T) {
 638 | 		// Create request with explicit bool values
 639 | 		args := map[string]interface{}{
 640 | 			"true_param":  true,
 641 | 			"false_param": false,
 642 | 		}
 643 | 		request := &mcpgo.CallToolRequest{
 644 | 			Arguments: args,
 645 | 		}
 646 | 
 647 | 		// Create result map
 648 | 		result := make(map[string]interface{})
 649 | 
 650 | 		// Validate both parameters
 651 | 		validator := NewValidator(request).
 652 | 			ValidateAndAddOptionalBool(result, "true_param").
 653 | 			ValidateAndAddOptionalBool(result, "false_param")
 654 | 
 655 | 		// Verify no errors occurred
 656 | 		assert.False(t, validator.HasErrors())
 657 | 
 658 | 		// Both parameters should be set in the result
 659 | 		assert.Equal(t, true, result["true_param"])
 660 | 		assert.Equal(t, false, result["false_param"])
 661 | 	})
 662 | 
 663 | 	t.Run("missing bool parameter", func(t *testing.T) {
 664 | 		// Create request without bool parameters
 665 | 		args := map[string]interface{}{
 666 | 			"other_param": "some value",
 667 | 		}
 668 | 		request := &mcpgo.CallToolRequest{
 669 | 			Arguments: args,
 670 | 		}
 671 | 
 672 | 		// Create result map
 673 | 		result := make(map[string]interface{})
 674 | 
 675 | 		// Try to validate missing bool parameters
 676 | 		validator := NewValidator(request).
 677 | 			ValidateAndAddOptionalBool(result, "true_param").
 678 | 			ValidateAndAddOptionalBool(result, "false_param")
 679 | 
 680 | 		// Verify no errors occurred
 681 | 		assert.False(t, validator.HasErrors())
 682 | 
 683 | 		// Result should be empty since no bool values were provided
 684 | 		assert.Empty(t, result)
 685 | 	})
 686 | 
 687 | 	t.Run("explicit bool values with 'To' functions", func(t *testing.T) {
 688 | 		// Create request with explicit bool values
 689 | 		args := map[string]interface{}{
 690 | 			"notify_sms":   true,
 691 | 			"notify_email": false,
 692 | 		}
 693 | 		request := &mcpgo.CallToolRequest{
 694 | 			Arguments: args,
 695 | 		}
 696 | 
 697 | 		// Create target map
 698 | 		target := make(map[string]interface{})
 699 | 
 700 | 		// Validate both parameters
 701 | 		validator := NewValidator(request).
 702 | 			ValidateAndAddOptionalBoolToPath(target, "notify_sms", "sms").
 703 | 			ValidateAndAddOptionalBoolToPath(target, "notify_email", "email")
 704 | 
 705 | 		// Verify no errors occurred
 706 | 		assert.False(t, validator.HasErrors())
 707 | 
 708 | 		// Both parameters should be set in the target map
 709 | 		assert.Equal(t, true, target["sms"])
 710 | 		assert.Equal(t, false, target["email"])
 711 | 	})
 712 | 
 713 | 	t.Run("missing bool parameter with 'To' functions", func(t *testing.T) {
 714 | 		// Create request without bool parameters
 715 | 		args := map[string]interface{}{
 716 | 			"other_param": "some value",
 717 | 		}
 718 | 		request := &mcpgo.CallToolRequest{
 719 | 			Arguments: args,
 720 | 		}
 721 | 
 722 | 		// Create target map
 723 | 		target := make(map[string]interface{})
 724 | 
 725 | 		// Try to validate missing bool parameters
 726 | 		validator := NewValidator(request).
 727 | 			ValidateAndAddOptionalBoolToPath(target, "notify_sms", "sms").
 728 | 			ValidateAndAddOptionalBoolToPath(target, "notify_email", "email")
 729 | 
 730 | 		// Verify no errors occurred
 731 | 		assert.False(t, validator.HasErrors())
 732 | 
 733 | 		// Target map should be empty since no bool values were provided
 734 | 		assert.Empty(t, target)
 735 | 	})
 736 | }
 737 | 
 738 | // Test for extractValueGeneric function edge cases
 739 | func TestExtractValueGeneric(t *testing.T) {
 740 | 	t.Run("invalid arguments type", func(t *testing.T) {
 741 | 		request := &mcpgo.CallToolRequest{
 742 | 			Arguments: "invalid_type", // Not a map
 743 | 		}
 744 | 
 745 | 		result, err := extractValueGeneric[string](request, "test", false)
 746 | 		assert.Error(t, err)
 747 | 		assert.Equal(t, "invalid arguments type", err.Error())
 748 | 		assert.Nil(t, result)
 749 | 	})
 750 | 
 751 | 	t.Run("json marshal error", func(t *testing.T) {
 752 | 		// Create a value that can't be marshaled to JSON
 753 | 		args := map[string]interface{}{
 754 | 			"test_param": make(chan int), // Channels can't be marshaled
 755 | 		}
 756 | 		request := &mcpgo.CallToolRequest{
 757 | 			Arguments: args,
 758 | 		}
 759 | 
 760 | 		result, err := extractValueGeneric[string](request, "test_param", false)
 761 | 		assert.Error(t, err)
 762 | 		assert.Equal(t, "invalid parameter type: test_param", err.Error())
 763 | 		assert.Nil(t, result)
 764 | 	})
 765 | 
 766 | 	t.Run("json unmarshal error", func(t *testing.T) {
 767 | 		// Provide a value that can't be unmarshaled to the target type
 768 | 		args := map[string]interface{}{
 769 | 			"test_param": []interface{}{1, 2, 3}, // Array can't be unmarshaled to string
 770 | 		}
 771 | 		request := &mcpgo.CallToolRequest{
 772 | 			Arguments: args,
 773 | 		}
 774 | 
 775 | 		result, err := extractValueGeneric[string](request, "test_param", false)
 776 | 		assert.Error(t, err)
 777 | 		assert.Equal(t, "invalid parameter type: test_param", err.Error())
 778 | 		assert.Nil(t, result)
 779 | 	})
 780 | }
 781 | 
 782 | // Test for validateAndAddRequired function
 783 | func TestValidateAndAddRequired(t *testing.T) {
 784 | 	t.Run("successful validation", func(t *testing.T) {
 785 | 		args := map[string]interface{}{
 786 | 			"test_param": "test_value",
 787 | 		}
 788 | 		request := &mcpgo.CallToolRequest{
 789 | 			Arguments: args,
 790 | 		}
 791 | 
 792 | 		params := make(map[string]interface{})
 793 | 		validator := NewValidator(request)
 794 | 
 795 | 		result := validateAndAddRequired[string](validator, params, "test_param")
 796 | 
 797 | 		assert.False(t, result.HasErrors())
 798 | 		assert.Equal(t, "test_value", params["test_param"])
 799 | 	})
 800 | 
 801 | 	t.Run("validation error", func(t *testing.T) {
 802 | 		request := &mcpgo.CallToolRequest{
 803 | 			Arguments: "invalid_type",
 804 | 		}
 805 | 
 806 | 		params := make(map[string]interface{})
 807 | 		validator := NewValidator(request)
 808 | 
 809 | 		result := validateAndAddRequired[string](validator, params, "test_param")
 810 | 
 811 | 		assert.True(t, result.HasErrors())
 812 | 		assert.Empty(t, params)
 813 | 	})
 814 | 
 815 | 	t.Run("nil value after successful extraction", func(t *testing.T) {
 816 | 		// This edge case is hard to trigger directly, but we can simulate it
 817 | 		// by using a type that extractValueGeneric might return as nil
 818 | 		args := map[string]interface{}{
 819 | 			"test_param": nil,
 820 | 		}
 821 | 		request := &mcpgo.CallToolRequest{
 822 | 			Arguments: args,
 823 | 		}
 824 | 
 825 | 		params := make(map[string]interface{})
 826 | 		validator := NewValidator(request)
 827 | 
 828 | 		result := validateAndAddRequired[string](validator, params, "test_param")
 829 | 
 830 | 		// This should result in an error because the parameter is required
 831 | 		assert.True(t, result.HasErrors())
 832 | 		assert.Empty(t, params)
 833 | 	})
 834 | }
 835 | 
 836 | // Test for validateAndAddOptional function
 837 | func TestValidateAndAddOptional(t *testing.T) {
 838 | 	t.Run("successful validation", func(t *testing.T) {
 839 | 		args := map[string]interface{}{
 840 | 			"test_param": "test_value",
 841 | 		}
 842 | 		request := &mcpgo.CallToolRequest{
 843 | 			Arguments: args,
 844 | 		}
 845 | 
 846 | 		params := make(map[string]interface{})
 847 | 		validator := NewValidator(request)
 848 | 
 849 | 		result := validateAndAddOptional[string](validator, params, "test_param")
 850 | 
 851 | 		assert.False(t, result.HasErrors())
 852 | 		assert.Equal(t, "test_value", params["test_param"])
 853 | 	})
 854 | 
 855 | 	t.Run("validation error", func(t *testing.T) {
 856 | 		request := &mcpgo.CallToolRequest{
 857 | 			Arguments: "invalid_type",
 858 | 		}
 859 | 
 860 | 		params := make(map[string]interface{})
 861 | 		validator := NewValidator(request)
 862 | 
 863 | 		result := validateAndAddOptional[string](validator, params, "test_param")
 864 | 
 865 | 		assert.True(t, result.HasErrors())
 866 | 		assert.Empty(t, params)
 867 | 	})
 868 | 
 869 | 	t.Run("nil value handling", func(t *testing.T) {
 870 | 		args := map[string]interface{}{
 871 | 			"test_param": nil,
 872 | 		}
 873 | 		request := &mcpgo.CallToolRequest{
 874 | 			Arguments: args,
 875 | 		}
 876 | 
 877 | 		params := make(map[string]interface{})
 878 | 		validator := NewValidator(request)
 879 | 
 880 | 		result := validateAndAddOptional[string](validator, params, "test_param")
 881 | 
 882 | 		assert.False(t, result.HasErrors())
 883 | 		assert.Empty(t, params)
 884 | 	})
 885 | }
 886 | 
 887 | // Test for validateAndAddToPath function
 888 | func TestValidateAndAddToPath(t *testing.T) {
 889 | 	t.Run("successful validation", func(t *testing.T) {
 890 | 		args := map[string]interface{}{
 891 | 			"test_param": "test_value",
 892 | 		}
 893 | 		request := &mcpgo.CallToolRequest{
 894 | 			Arguments: args,
 895 | 		}
 896 | 
 897 | 		target := make(map[string]interface{})
 898 | 		validator := NewValidator(request)
 899 | 
 900 | 		result := validateAndAddToPath[string](
 901 | 			validator, target, "test_param", "target_key")
 902 | 
 903 | 		assert.False(t, result.HasErrors())
 904 | 		assert.Equal(t, "test_value", target["target_key"])
 905 | 	})
 906 | 
 907 | 	t.Run("validation error", func(t *testing.T) {
 908 | 		request := &mcpgo.CallToolRequest{
 909 | 			Arguments: "invalid_type",
 910 | 		}
 911 | 
 912 | 		target := make(map[string]interface{})
 913 | 		validator := NewValidator(request)
 914 | 
 915 | 		result := validateAndAddToPath[string](
 916 | 			validator, target, "test_param", "target_key")
 917 | 
 918 | 		assert.True(t, result.HasErrors())
 919 | 		assert.Empty(t, target)
 920 | 	})
 921 | 
 922 | 	t.Run("nil value handling", func(t *testing.T) {
 923 | 		args := map[string]interface{}{
 924 | 			"test_param": nil,
 925 | 		}
 926 | 		request := &mcpgo.CallToolRequest{
 927 | 			Arguments: args,
 928 | 		}
 929 | 
 930 | 		target := make(map[string]interface{})
 931 | 		validator := NewValidator(request)
 932 | 
 933 | 		result := validateAndAddToPath[string](
 934 | 			validator, target, "test_param", "target_key")
 935 | 
 936 | 		assert.False(t, result.HasErrors())
 937 | 		assert.Empty(t, target)
 938 | 	})
 939 | }
 940 | 
 941 | // Test for ValidateAndAddPagination function
 942 | func TestValidateAndAddPagination(t *testing.T) {
 943 | 	t.Run("all pagination parameters", func(t *testing.T) {
 944 | 		args := map[string]interface{}{
 945 | 			"count": 10,
 946 | 			"skip":  5,
 947 | 		}
 948 | 		request := &mcpgo.CallToolRequest{
 949 | 			Arguments: args,
 950 | 		}
 951 | 
 952 | 		params := make(map[string]interface{})
 953 | 		validator := NewValidator(request).ValidateAndAddPagination(params)
 954 | 
 955 | 		assert.False(t, validator.HasErrors())
 956 | 		assert.Equal(t, int64(10), params["count"])
 957 | 		assert.Equal(t, int64(5), params["skip"])
 958 | 	})
 959 | 
 960 | 	t.Run("missing pagination parameters", func(t *testing.T) {
 961 | 		args := map[string]interface{}{}
 962 | 		request := &mcpgo.CallToolRequest{
 963 | 			Arguments: args,
 964 | 		}
 965 | 
 966 | 		params := make(map[string]interface{})
 967 | 		validator := NewValidator(request).ValidateAndAddPagination(params)
 968 | 
 969 | 		assert.False(t, validator.HasErrors())
 970 | 		assert.Empty(t, params)
 971 | 	})
 972 | 
 973 | 	t.Run("invalid count type", func(t *testing.T) {
 974 | 		args := map[string]interface{}{
 975 | 			"count": "invalid",
 976 | 		}
 977 | 		request := &mcpgo.CallToolRequest{
 978 | 			Arguments: args,
 979 | 		}
 980 | 
 981 | 		params := make(map[string]interface{})
 982 | 		validator := NewValidator(request).ValidateAndAddPagination(params)
 983 | 
 984 | 		assert.True(t, validator.HasErrors())
 985 | 	})
 986 | }
 987 | 
 988 | // Test for ValidateAndAddExpand function
 989 | func TestValidateAndAddExpand(t *testing.T) {
 990 | 	t.Run("valid expand parameter", func(t *testing.T) {
 991 | 		args := map[string]interface{}{
 992 | 			"expand": []string{"payments", "customer"},
 993 | 		}
 994 | 		request := &mcpgo.CallToolRequest{
 995 | 			Arguments: args,
 996 | 		}
 997 | 
 998 | 		params := make(map[string]interface{})
 999 | 		validator := NewValidator(request).ValidateAndAddExpand(params)
1000 | 
1001 | 		assert.False(t, validator.HasErrors())
1002 | 		// The function sets expand[] for each value, so check the last one
1003 | 		assert.Equal(t, "customer", params["expand[]"])
1004 | 	})
1005 | 
1006 | 	t.Run("missing expand parameter", func(t *testing.T) {
1007 | 		args := map[string]interface{}{}
1008 | 		request := &mcpgo.CallToolRequest{
1009 | 			Arguments: args,
1010 | 		}
1011 | 
1012 | 		params := make(map[string]interface{})
1013 | 		validator := NewValidator(request).ValidateAndAddExpand(params)
1014 | 
1015 | 		assert.False(t, validator.HasErrors())
1016 | 		assert.Empty(t, params)
1017 | 	})
1018 | 
1019 | 	t.Run("invalid expand type", func(t *testing.T) {
1020 | 		args := map[string]interface{}{
1021 | 			"expand": "invalid", // Should be []string, not string
1022 | 		}
1023 | 		request := &mcpgo.CallToolRequest{
1024 | 			Arguments: args,
1025 | 		}
1026 | 
1027 | 		params := make(map[string]interface{})
1028 | 		validator := NewValidator(request).ValidateAndAddExpand(params)
1029 | 
1030 | 		assert.True(t, validator.HasErrors())
1031 | 	})
1032 | }
1033 | 
1034 | // Test for token validation functions edge cases
1035 | func TestTokenValidationEdgeCases(t *testing.T) {
1036 | 	t.Run("validateTokenMaxAmount - int conversion", func(t *testing.T) {
1037 | 		token := map[string]interface{}{
1038 | 			"max_amount": 100, // int instead of float64
1039 | 		}
1040 | 
1041 | 		request := &mcpgo.CallToolRequest{Arguments: map[string]interface{}{}}
1042 | 		validator := NewValidator(request).validateTokenMaxAmount(token)
1043 | 
1044 | 		assert.False(t, validator.HasErrors())
1045 | 		assert.Equal(t, float64(100), token["max_amount"])
1046 | 	})
1047 | 
1048 | 	t.Run("validateTokenExpireAt - int conversion", func(t *testing.T) {
1049 | 		token := map[string]interface{}{
1050 | 			"expire_at": 1234567890, // int instead of float64
1051 | 		}
1052 | 
1053 | 		request := &mcpgo.CallToolRequest{Arguments: map[string]interface{}{}}
1054 | 		validator := NewValidator(request).validateTokenExpireAt(token)
1055 | 
1056 | 		assert.False(t, validator.HasErrors())
1057 | 		assert.Equal(t, float64(1234567890), token["expire_at"])
1058 | 	})
1059 | 
1060 | 	t.Run("validateTokenExpireAt - zero value", func(t *testing.T) {
1061 | 		token := map[string]interface{}{
1062 | 			"expire_at": 0,
1063 | 		}
1064 | 
1065 | 		request := &mcpgo.CallToolRequest{Arguments: map[string]interface{}{}}
1066 | 		validator := NewValidator(request).validateTokenExpireAt(token)
1067 | 
1068 | 		assert.True(t, validator.HasErrors())
1069 | 	})
1070 | 
1071 | 	t.Run("validateTokenMaxAmount - zero value", func(t *testing.T) {
1072 | 		token := map[string]interface{}{
1073 | 			"max_amount": 0,
1074 | 		}
1075 | 
1076 | 		request := &mcpgo.CallToolRequest{Arguments: map[string]interface{}{}}
1077 | 		validator := NewValidator(request).validateTokenMaxAmount(token)
1078 | 
1079 | 		assert.True(t, validator.HasErrors())
1080 | 	})
1081 | }
1082 | 
1083 | // Test for ValidateAndAddToken edge cases
1084 | func TestValidateAndAddTokenEdgeCases(t *testing.T) {
1085 | 	t.Run("token extraction error", func(t *testing.T) {
1086 | 		request := &mcpgo.CallToolRequest{
1087 | 			Arguments: "invalid_type",
1088 | 		}
1089 | 
1090 | 		params := make(map[string]interface{})
1091 | 		validator := NewValidator(request).ValidateAndAddToken(params, "token")
1092 | 
1093 | 		assert.True(t, validator.HasErrors())
1094 | 		assert.Empty(t, params)
1095 | 	})
1096 | 
1097 | 	t.Run("nil token value", func(t *testing.T) {
1098 | 		args := map[string]interface{}{
1099 | 			"token": nil,
1100 | 		}
1101 | 		request := &mcpgo.CallToolRequest{
1102 | 			Arguments: args,
1103 | 		}
1104 | 
1105 | 		params := make(map[string]interface{})
1106 | 		validator := NewValidator(request).ValidateAndAddToken(params, "token")
1107 | 
1108 | 		assert.False(t, validator.HasErrors())
1109 | 		assert.Empty(t, params)
1110 | 	})
1111 | 
1112 | 	t.Run("token validation errors", func(t *testing.T) {
1113 | 		args := map[string]interface{}{
1114 | 			"token": map[string]interface{}{
1115 | 				"max_amount": -100, // Invalid value
1116 | 			},
1117 | 		}
1118 | 		request := &mcpgo.CallToolRequest{
1119 | 			Arguments: args,
1120 | 		}
1121 | 
1122 | 		params := make(map[string]interface{})
1123 | 		validator := NewValidator(request).ValidateAndAddToken(params, "token")
1124 | 
1125 | 		assert.True(t, validator.HasErrors())
1126 | 		assert.Empty(t, params)
1127 | 	})
1128 | }
1129 | 
```
Page 4/5FirstPrevNextLast