github.com/hashicorp/vault/sdk@v0.13.0/framework/backend_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package framework 5 6 import ( 7 "context" 8 "fmt" 9 "net/http" 10 "reflect" 11 "strings" 12 "sync/atomic" 13 "testing" 14 "time" 15 16 "github.com/hashicorp/go-secure-stdlib/strutil" 17 "github.com/hashicorp/vault/sdk/helper/consts" 18 "github.com/hashicorp/vault/sdk/logical" 19 "github.com/stretchr/testify/require" 20 ) 21 22 func BenchmarkBackendRoute(b *testing.B) { 23 patterns := []string{ 24 "foo", 25 "bar/(?P<name>.+?)", 26 "baz/(?P<name>what)", 27 `aws/policy/(?P<policy>\w)`, 28 `aws/(?P<policy>\w)`, 29 } 30 31 backend := &Backend{Paths: make([]*Path, 0, len(patterns))} 32 for _, p := range patterns { 33 backend.Paths = append(backend.Paths, &Path{Pattern: p}) 34 } 35 36 // Warm any caches 37 backend.Route("aws/policy/foo") 38 39 // Reset the timer since we did a lot above 40 b.ResetTimer() 41 42 // Run through and route. We do a sanity check of the return value 43 for i := 0; i < b.N; i++ { 44 if p := backend.Route("aws/policy/foo"); p == nil { 45 b.Fatal("p should not be nil") 46 } 47 } 48 } 49 50 func TestBackend_impl(t *testing.T) { 51 var _ logical.Backend = new(Backend) 52 } 53 54 func TestBackendHandleRequestFieldWarnings(t *testing.T) { 55 handler := func(ctx context.Context, req *logical.Request, data *FieldData) (*logical.Response, error) { 56 return &logical.Response{ 57 Data: map[string]interface{}{ 58 "an_int": data.Get("an_int"), 59 "a_string": data.Get("a_string"), 60 "name": data.Get("name"), 61 }, 62 }, nil 63 } 64 65 backend := &Backend{ 66 Paths: []*Path{ 67 { 68 Pattern: "foo/bar/(?P<name>.+)", 69 Fields: map[string]*FieldSchema{ 70 "an_int": {Type: TypeInt}, 71 "a_string": {Type: TypeString}, 72 "name": {Type: TypeString}, 73 }, 74 Operations: map[logical.Operation]OperationHandler{ 75 logical.UpdateOperation: &PathOperation{Callback: handler}, 76 }, 77 }, 78 }, 79 } 80 ctx := context.Background() 81 resp, err := backend.HandleRequest(ctx, &logical.Request{ 82 Operation: logical.UpdateOperation, 83 Path: "foo/bar/baz", 84 Data: map[string]interface{}{ 85 "an_int": 10, 86 "a_string": "accepted", 87 "unrecognized1": "unrecognized", 88 "unrecognized2": 20.2, 89 "name": "noop", 90 }, 91 }) 92 require.NoError(t, err) 93 require.NotNil(t, resp) 94 t.Log(resp.Warnings) 95 require.Len(t, resp.Warnings, 2) 96 require.True(t, strutil.StrListContains(resp.Warnings, "Endpoint ignored these unrecognized parameters: [unrecognized1 unrecognized2]")) 97 require.True(t, strutil.StrListContains(resp.Warnings, "Endpoint replaced the value of these parameters with the values captured from the endpoint's path: [name]")) 98 } 99 100 func TestBackendHandleRequest(t *testing.T) { 101 callback := func(ctx context.Context, req *logical.Request, data *FieldData) (*logical.Response, error) { 102 return &logical.Response{ 103 Data: map[string]interface{}{ 104 "value": data.Get("value"), 105 }, 106 }, nil 107 } 108 handler := func(ctx context.Context, req *logical.Request, data *FieldData) (*logical.Response, error) { 109 return &logical.Response{ 110 Data: map[string]interface{}{ 111 "amount": data.Get("amount"), 112 }, 113 }, nil 114 } 115 116 b := &Backend{ 117 Paths: []*Path{ 118 { 119 Pattern: "foo/bar", 120 Fields: map[string]*FieldSchema{ 121 "value": {Type: TypeInt}, 122 }, 123 Callbacks: map[logical.Operation]OperationFunc{ 124 logical.ReadOperation: callback, 125 }, 126 }, 127 { 128 Pattern: "foo/baz/handler", 129 Fields: map[string]*FieldSchema{ 130 "amount": {Type: TypeInt}, 131 }, 132 Operations: map[logical.Operation]OperationHandler{ 133 logical.ReadOperation: &PathOperation{Callback: handler}, 134 }, 135 }, 136 { 137 Pattern: "foo/both/handler", 138 Fields: map[string]*FieldSchema{ 139 "amount": {Type: TypeInt}, 140 }, 141 Callbacks: map[logical.Operation]OperationFunc{ 142 logical.ReadOperation: callback, 143 }, 144 Operations: map[logical.Operation]OperationHandler{ 145 logical.ReadOperation: &PathOperation{Callback: handler}, 146 }, 147 }, 148 }, 149 system: &logical.StaticSystemView{}, 150 } 151 152 for _, path := range []string{"foo/bar", "foo/baz/handler", "foo/both/handler"} { 153 key := "value" 154 if strings.Contains(path, "handler") { 155 key = "amount" 156 } 157 resp, err := b.HandleRequest(context.Background(), &logical.Request{ 158 Operation: logical.ReadOperation, 159 Path: path, 160 Data: map[string]interface{}{key: "42"}, 161 }) 162 if err != nil { 163 t.Fatalf("err: %s", err) 164 } 165 if resp.Data[key] != 42 { 166 t.Fatalf("bad: %#v", resp) 167 } 168 } 169 } 170 171 func TestBackendHandleRequest_Forwarding(t *testing.T) { 172 tests := map[string]struct { 173 fwdStandby bool 174 fwdSecondary bool 175 isLocal bool 176 isStandby bool 177 isSecondary bool 178 expectFwd bool 179 nilSysView bool 180 }{ 181 "no forward": { 182 expectFwd: false, 183 }, 184 "no forward, local restricted": { 185 isSecondary: true, 186 fwdSecondary: true, 187 isLocal: true, 188 expectFwd: false, 189 }, 190 "no forward, forwarding not requested": { 191 isSecondary: true, 192 isStandby: true, 193 expectFwd: false, 194 }, 195 "forward, secondary": { 196 fwdSecondary: true, 197 isSecondary: true, 198 expectFwd: true, 199 }, 200 "forward, standby": { 201 fwdStandby: true, 202 isStandby: true, 203 expectFwd: true, 204 }, 205 "no forward, only secondary": { 206 fwdSecondary: true, 207 isStandby: true, 208 expectFwd: false, 209 }, 210 "no forward, only standby": { 211 fwdStandby: true, 212 isSecondary: true, 213 expectFwd: false, 214 }, 215 "nil system view": { 216 nilSysView: true, 217 expectFwd: false, 218 }, 219 } 220 221 for name, test := range tests { 222 t.Run(name, func(t *testing.T) { 223 var replState consts.ReplicationState 224 if test.isStandby { 225 replState.AddState(consts.ReplicationPerformanceStandby) 226 } 227 if test.isSecondary { 228 replState.AddState(consts.ReplicationPerformanceSecondary) 229 } 230 231 b := &Backend{ 232 Paths: []*Path{ 233 { 234 Pattern: "foo", 235 Operations: map[logical.Operation]OperationHandler{ 236 logical.ReadOperation: &PathOperation{ 237 Callback: func(ctx context.Context, req *logical.Request, data *FieldData) (*logical.Response, error) { 238 return nil, nil 239 }, 240 ForwardPerformanceSecondary: test.fwdSecondary, 241 ForwardPerformanceStandby: test.fwdStandby, 242 }, 243 }, 244 }, 245 }, 246 247 system: &logical.StaticSystemView{ 248 LocalMountVal: test.isLocal, 249 ReplicationStateVal: replState, 250 }, 251 } 252 253 if test.nilSysView { 254 b.system = nil 255 } 256 257 _, err := b.HandleRequest(context.Background(), &logical.Request{ 258 Operation: logical.ReadOperation, 259 Path: "foo", 260 }) 261 262 if !test.expectFwd && err != nil { 263 t.Fatalf("unexpected err: %v", err) 264 } 265 if test.expectFwd && err != logical.ErrReadOnly { 266 t.Fatalf("expected ErrReadOnly, got: %v", err) 267 } 268 }) 269 } 270 } 271 272 func TestBackendHandleRequest_badwrite(t *testing.T) { 273 callback := func(ctx context.Context, req *logical.Request, data *FieldData) (*logical.Response, error) { 274 return &logical.Response{ 275 Data: map[string]interface{}{ 276 "value": data.Get("value").(bool), 277 }, 278 }, nil 279 } 280 281 b := &Backend{ 282 Paths: []*Path{ 283 { 284 Pattern: "foo/bar", 285 Fields: map[string]*FieldSchema{ 286 "value": {Type: TypeBool}, 287 }, 288 Callbacks: map[logical.Operation]OperationFunc{ 289 logical.UpdateOperation: callback, 290 }, 291 }, 292 }, 293 } 294 295 resp, err := b.HandleRequest(context.Background(), &logical.Request{ 296 Operation: logical.UpdateOperation, 297 Path: "foo/bar", 298 Data: map[string]interface{}{"value": "3false3"}, 299 }) 300 if err != nil { 301 t.Fatalf("err: %s", err) 302 } 303 304 if !strings.Contains(resp.Data["error"].(string), "Field validation failed") { 305 t.Fatalf("bad: %#v", resp) 306 } 307 } 308 309 func TestBackendHandleRequest_404(t *testing.T) { 310 callback := func(ctx context.Context, req *logical.Request, data *FieldData) (*logical.Response, error) { 311 return &logical.Response{ 312 Data: map[string]interface{}{ 313 "value": data.Get("value"), 314 }, 315 }, nil 316 } 317 318 b := &Backend{ 319 Paths: []*Path{ 320 { 321 Pattern: `foo/bar`, 322 Fields: map[string]*FieldSchema{ 323 "value": {Type: TypeInt}, 324 }, 325 Callbacks: map[logical.Operation]OperationFunc{ 326 logical.ReadOperation: callback, 327 }, 328 }, 329 }, 330 } 331 332 _, err := b.HandleRequest(context.Background(), &logical.Request{ 333 Operation: logical.ReadOperation, 334 Path: "foo/baz", 335 Data: map[string]interface{}{"value": "84"}, 336 }) 337 if err != logical.ErrUnsupportedPath { 338 t.Fatalf("err: %s", err) 339 } 340 } 341 342 func TestBackendHandleRequest_help(t *testing.T) { 343 b := &Backend{ 344 Paths: []*Path{ 345 { 346 Pattern: "foo/bar", 347 Fields: map[string]*FieldSchema{ 348 "value": {Type: TypeInt}, 349 }, 350 HelpSynopsis: "foo", 351 HelpDescription: "bar", 352 }, 353 }, 354 } 355 356 resp, err := b.HandleRequest(context.Background(), &logical.Request{ 357 Operation: logical.HelpOperation, 358 Path: "foo/bar", 359 Data: map[string]interface{}{"value": "42"}, 360 }) 361 if err != nil { 362 t.Fatalf("err: %s", err) 363 } 364 if resp.Data["help"] == nil { 365 t.Fatalf("bad: %#v", resp) 366 } 367 } 368 369 func TestBackendHandleRequest_helpRoot(t *testing.T) { 370 b := &Backend{ 371 Help: "42", 372 } 373 374 resp, err := b.HandleRequest(context.Background(), &logical.Request{ 375 Operation: logical.HelpOperation, 376 Path: "", 377 }) 378 if err != nil { 379 t.Fatalf("err: %s", err) 380 } 381 if resp.Data["help"] == nil { 382 t.Fatalf("bad: %#v", resp) 383 } 384 } 385 386 func TestBackendHandleRequest_renewAuth(t *testing.T) { 387 b := &Backend{} 388 389 resp, err := b.HandleRequest(context.Background(), logical.RenewAuthRequest("/foo", &logical.Auth{}, nil)) 390 if err != nil { 391 t.Fatalf("err: %s", err) 392 } 393 if !resp.IsError() { 394 t.Fatalf("bad: %#v", resp) 395 } 396 } 397 398 func TestBackendHandleRequest_renewAuthCallback(t *testing.T) { 399 called := new(uint32) 400 callback := func(context.Context, *logical.Request, *FieldData) (*logical.Response, error) { 401 atomic.AddUint32(called, 1) 402 return nil, nil 403 } 404 405 b := &Backend{ 406 AuthRenew: callback, 407 } 408 409 _, err := b.HandleRequest(context.Background(), logical.RenewAuthRequest("/foo", &logical.Auth{}, nil)) 410 if err != nil { 411 t.Fatalf("err: %s", err) 412 } 413 if v := atomic.LoadUint32(called); v != 1 { 414 t.Fatalf("bad: %#v", v) 415 } 416 } 417 418 func TestBackendHandleRequest_renew(t *testing.T) { 419 called := new(uint32) 420 callback := func(context.Context, *logical.Request, *FieldData) (*logical.Response, error) { 421 atomic.AddUint32(called, 1) 422 return nil, nil 423 } 424 425 secret := &Secret{ 426 Type: "foo", 427 Renew: callback, 428 } 429 b := &Backend{ 430 Secrets: []*Secret{secret}, 431 } 432 433 _, err := b.HandleRequest(context.Background(), logical.RenewRequest("/foo", secret.Response(nil, nil).Secret, nil)) 434 if err != nil { 435 t.Fatalf("err: %s", err) 436 } 437 if v := atomic.LoadUint32(called); v != 1 { 438 t.Fatalf("bad: %#v", v) 439 } 440 } 441 442 func TestBackendHandleRequest_revoke(t *testing.T) { 443 called := new(uint32) 444 callback := func(context.Context, *logical.Request, *FieldData) (*logical.Response, error) { 445 atomic.AddUint32(called, 1) 446 return nil, nil 447 } 448 449 secret := &Secret{ 450 Type: "foo", 451 Revoke: callback, 452 } 453 b := &Backend{ 454 Secrets: []*Secret{secret}, 455 } 456 457 _, err := b.HandleRequest(context.Background(), logical.RevokeRequest("/foo", secret.Response(nil, nil).Secret, nil)) 458 if err != nil { 459 t.Fatalf("err: %s", err) 460 } 461 if v := atomic.LoadUint32(called); v != 1 { 462 t.Fatalf("bad: %#v", v) 463 } 464 } 465 466 func TestBackendHandleRequest_rollback(t *testing.T) { 467 called := new(uint32) 468 callback := func(_ context.Context, req *logical.Request, kind string, data interface{}) error { 469 if data == "foo" { 470 atomic.AddUint32(called, 1) 471 } 472 return nil 473 } 474 475 b := &Backend{ 476 WALRollback: callback, 477 WALRollbackMinAge: 1 * time.Millisecond, 478 } 479 480 storage := new(logical.InmemStorage) 481 if _, err := PutWAL(context.Background(), storage, "kind", "foo"); err != nil { 482 t.Fatalf("err: %s", err) 483 } 484 485 time.Sleep(10 * time.Millisecond) 486 487 _, err := b.HandleRequest(context.Background(), &logical.Request{ 488 Operation: logical.RollbackOperation, 489 Path: "", 490 Storage: storage, 491 }) 492 if err != nil { 493 t.Fatalf("err: %s", err) 494 } 495 if v := atomic.LoadUint32(called); v != 1 { 496 t.Fatalf("bad: %#v", v) 497 } 498 } 499 500 func TestBackendHandleRequest_rollbackMinAge(t *testing.T) { 501 called := new(uint32) 502 callback := func(_ context.Context, req *logical.Request, kind string, data interface{}) error { 503 if data == "foo" { 504 atomic.AddUint32(called, 1) 505 } 506 return nil 507 } 508 509 b := &Backend{ 510 WALRollback: callback, 511 WALRollbackMinAge: 5 * time.Second, 512 } 513 514 storage := new(logical.InmemStorage) 515 if _, err := PutWAL(context.Background(), storage, "kind", "foo"); err != nil { 516 t.Fatalf("err: %s", err) 517 } 518 519 _, err := b.HandleRequest(context.Background(), &logical.Request{ 520 Operation: logical.RollbackOperation, 521 Path: "", 522 Storage: storage, 523 }) 524 if err != nil { 525 t.Fatalf("err: %s", err) 526 } 527 if v := atomic.LoadUint32(called); v != 0 { 528 t.Fatalf("bad: %#v", v) 529 } 530 } 531 532 func TestBackendHandleRequest_unsupportedOperation(t *testing.T) { 533 callback := func(ctx context.Context, req *logical.Request, data *FieldData) (*logical.Response, error) { 534 return &logical.Response{ 535 Data: map[string]interface{}{ 536 "value": data.Get("value"), 537 }, 538 }, nil 539 } 540 541 b := &Backend{ 542 Paths: []*Path{ 543 { 544 Pattern: `foo/bar`, 545 Fields: map[string]*FieldSchema{ 546 "value": {Type: TypeInt}, 547 }, 548 Callbacks: map[logical.Operation]OperationFunc{ 549 logical.ReadOperation: callback, 550 }, 551 }, 552 }, 553 } 554 555 _, err := b.HandleRequest(context.Background(), &logical.Request{ 556 Operation: logical.UpdateOperation, 557 Path: "foo/bar", 558 Data: map[string]interface{}{"value": "84"}, 559 }) 560 if err != logical.ErrUnsupportedOperation { 561 t.Fatalf("err: %s", err) 562 } 563 } 564 565 func TestBackendHandleRequest_urlPriority(t *testing.T) { 566 callback := func(ctx context.Context, req *logical.Request, data *FieldData) (*logical.Response, error) { 567 return &logical.Response{ 568 Data: map[string]interface{}{ 569 "value": data.Get("value"), 570 }, 571 }, nil 572 } 573 574 b := &Backend{ 575 Paths: []*Path{ 576 { 577 Pattern: `foo/(?P<value>\d+)`, 578 Fields: map[string]*FieldSchema{ 579 "value": {Type: TypeInt}, 580 }, 581 Callbacks: map[logical.Operation]OperationFunc{ 582 logical.ReadOperation: callback, 583 }, 584 }, 585 }, 586 } 587 588 resp, err := b.HandleRequest(context.Background(), &logical.Request{ 589 Operation: logical.ReadOperation, 590 Path: "foo/42", 591 Data: map[string]interface{}{"value": "84"}, 592 }) 593 if err != nil { 594 t.Fatalf("err: %s", err) 595 } 596 if resp.Data["value"] != 42 { 597 t.Fatalf("bad: %#v", resp) 598 } 599 } 600 601 func TestBackendRoute(t *testing.T) { 602 cases := map[string]struct { 603 Patterns []string 604 Path string 605 Match string 606 }{ 607 "no match": { 608 []string{"foo"}, 609 "bar", 610 "", 611 }, 612 613 "exact": { 614 []string{"foo"}, 615 "foo", 616 "^foo$", 617 }, 618 619 "regexp": { 620 []string{"fo+"}, 621 "foo", 622 "^fo+$", 623 }, 624 625 "anchor-start": { 626 []string{"bar"}, 627 "foobar", 628 "", 629 }, 630 631 "anchor-end": { 632 []string{"bar"}, 633 "barfoo", 634 "", 635 }, 636 637 "anchor-ambiguous": { 638 []string{"mounts", "sys/mounts"}, 639 "sys/mounts", 640 "^sys/mounts$", 641 }, 642 } 643 644 for n, tc := range cases { 645 paths := make([]*Path, len(tc.Patterns)) 646 for i, pattern := range tc.Patterns { 647 paths[i] = &Path{Pattern: pattern} 648 } 649 650 b := &Backend{Paths: paths} 651 result := b.Route(tc.Path) 652 match := "" 653 if result != nil { 654 match = result.Pattern 655 } 656 657 if match != tc.Match { 658 t.Fatalf("bad: %s\n\nExpected: %s\nGot: %s", 659 n, tc.Match, match) 660 } 661 } 662 } 663 664 func TestBackendSecret(t *testing.T) { 665 cases := map[string]struct { 666 Secrets []*Secret 667 Search string 668 Match bool 669 }{ 670 "no match": { 671 []*Secret{{Type: "foo"}}, 672 "bar", 673 false, 674 }, 675 676 "match": { 677 []*Secret{{Type: "foo"}}, 678 "foo", 679 true, 680 }, 681 } 682 683 for n, tc := range cases { 684 b := &Backend{Secrets: tc.Secrets} 685 result := b.Secret(tc.Search) 686 if tc.Match != (result != nil) { 687 t.Fatalf("bad: %s\n\nExpected match: %v", n, tc.Match) 688 } 689 if result != nil && result.Type != tc.Search { 690 t.Fatalf("bad: %s\n\nExpected matching type: %#v", n, result) 691 } 692 } 693 } 694 695 func TestFieldSchemaDefaultOrZero(t *testing.T) { 696 cases := map[string]struct { 697 Schema *FieldSchema 698 Value interface{} 699 }{ 700 "default set": { 701 &FieldSchema{Type: TypeString, Default: "foo"}, 702 "foo", 703 }, 704 705 "default not set": { 706 &FieldSchema{Type: TypeString}, 707 "", 708 }, 709 710 "default duration set": { 711 &FieldSchema{Type: TypeDurationSecond, Default: 60}, 712 60, 713 }, 714 715 "default duration int64": { 716 &FieldSchema{Type: TypeDurationSecond, Default: int64(60)}, 717 60, 718 }, 719 720 "default duration string": { 721 &FieldSchema{Type: TypeDurationSecond, Default: "60s"}, 722 60, 723 }, 724 725 "illegal default duration string": { 726 &FieldSchema{Type: TypeDurationSecond, Default: "h1"}, 727 0, 728 }, 729 730 "default duration time.Duration": { 731 &FieldSchema{Type: TypeDurationSecond, Default: 60 * time.Second}, 732 60, 733 }, 734 735 "default duration not set": { 736 &FieldSchema{Type: TypeDurationSecond}, 737 0, 738 }, 739 740 "default signed positive duration set": { 741 &FieldSchema{Type: TypeSignedDurationSecond, Default: 60}, 742 60, 743 }, 744 745 "default signed positive duration int64": { 746 &FieldSchema{Type: TypeSignedDurationSecond, Default: int64(60)}, 747 60, 748 }, 749 750 "default signed positive duration string": { 751 &FieldSchema{Type: TypeSignedDurationSecond, Default: "60s"}, 752 60, 753 }, 754 755 "illegal default signed duration string": { 756 &FieldSchema{Type: TypeDurationSecond, Default: "-h1"}, 757 0, 758 }, 759 760 "default signed positive duration time.Duration": { 761 &FieldSchema{Type: TypeSignedDurationSecond, Default: 60 * time.Second}, 762 60, 763 }, 764 765 "default signed negative duration set": { 766 &FieldSchema{Type: TypeSignedDurationSecond, Default: -60}, 767 -60, 768 }, 769 770 "default signed negative duration int64": { 771 &FieldSchema{Type: TypeSignedDurationSecond, Default: int64(-60)}, 772 -60, 773 }, 774 775 "default signed negative duration string": { 776 &FieldSchema{Type: TypeSignedDurationSecond, Default: "-60s"}, 777 -60, 778 }, 779 780 "default signed negative duration time.Duration": { 781 &FieldSchema{Type: TypeSignedDurationSecond, Default: -60 * time.Second}, 782 -60, 783 }, 784 785 "default signed negative duration not set": { 786 &FieldSchema{Type: TypeSignedDurationSecond}, 787 0, 788 }, 789 "default header not set": { 790 &FieldSchema{Type: TypeHeader}, 791 http.Header{}, 792 }, 793 } 794 795 for name, tc := range cases { 796 actual := tc.Schema.DefaultOrZero() 797 if !reflect.DeepEqual(actual, tc.Value) { 798 t.Errorf("bad: %s\n\nExpected: %#v\nGot: %#v", 799 name, tc.Value, actual) 800 } 801 } 802 } 803 804 func TestInitializeBackend(t *testing.T) { 805 var inited bool 806 backend := &Backend{InitializeFunc: func(context.Context, *logical.InitializationRequest) error { 807 inited = true 808 return nil 809 }} 810 811 backend.Initialize(nil, &logical.InitializationRequest{Storage: nil}) 812 813 if !inited { 814 t.Fatal("backend should be open") 815 } 816 } 817 818 // TestFieldTypeMethods tries to ensure our switch-case statements for the 819 // FieldType "enum" are complete. 820 func TestFieldTypeMethods(t *testing.T) { 821 unknownFormat := convertType(TypeInvalid).format 822 823 for i := TypeInvalid + 1; i < typeInvalidMax; i++ { 824 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { 825 if i.String() == TypeInvalid.String() { 826 t.Errorf("unknown type string for %d", i) 827 } 828 829 if convertType(i).format == unknownFormat { 830 t.Errorf("unknown schema for %d", i) 831 } 832 833 _ = i.Zero() 834 }) 835 } 836 }