github.com/kevinklinger/open_terraform@v1.3.6/noninternal/plugin/grpc_provider_test.go (about) 1 package plugin 2 3 import ( 4 "bytes" 5 "fmt" 6 "testing" 7 8 "github.com/golang/mock/gomock" 9 "github.com/google/go-cmp/cmp" 10 "github.com/kevinklinger/open_terraform/noninternal/configs/hcl2shim" 11 "github.com/kevinklinger/open_terraform/noninternal/providers" 12 "github.com/kevinklinger/open_terraform/noninternal/tfdiags" 13 "github.com/zclconf/go-cty/cty" 14 15 mockproto "github.com/kevinklinger/open_terraform/noninternal/plugin/mock_proto" 16 proto "github.com/kevinklinger/open_terraform/noninternal/tfplugin5" 17 ) 18 19 var _ providers.Interface = (*GRPCProvider)(nil) 20 21 func mockProviderClient(t *testing.T) *mockproto.MockProviderClient { 22 ctrl := gomock.NewController(t) 23 client := mockproto.NewMockProviderClient(ctrl) 24 25 // we always need a GetSchema method 26 client.EXPECT().GetSchema( 27 gomock.Any(), 28 gomock.Any(), 29 gomock.Any(), 30 ).Return(providerProtoSchema(), nil) 31 32 return client 33 } 34 35 func checkDiags(t *testing.T, d tfdiags.Diagnostics) { 36 t.Helper() 37 if d.HasErrors() { 38 t.Fatal(d.Err()) 39 } 40 } 41 42 // checkDiagsHasError ensures error diagnostics are present or fails the test. 43 func checkDiagsHasError(t *testing.T, d tfdiags.Diagnostics) { 44 t.Helper() 45 46 if !d.HasErrors() { 47 t.Fatal("expected error diagnostics") 48 } 49 } 50 51 func providerProtoSchema() *proto.GetProviderSchema_Response { 52 return &proto.GetProviderSchema_Response{ 53 Provider: &proto.Schema{ 54 Block: &proto.Schema_Block{ 55 Attributes: []*proto.Schema_Attribute{ 56 { 57 Name: "attr", 58 Type: []byte(`"string"`), 59 Required: true, 60 }, 61 }, 62 }, 63 }, 64 ResourceSchemas: map[string]*proto.Schema{ 65 "resource": &proto.Schema{ 66 Version: 1, 67 Block: &proto.Schema_Block{ 68 Attributes: []*proto.Schema_Attribute{ 69 { 70 Name: "attr", 71 Type: []byte(`"string"`), 72 Required: true, 73 }, 74 }, 75 }, 76 }, 77 }, 78 DataSourceSchemas: map[string]*proto.Schema{ 79 "data": &proto.Schema{ 80 Version: 1, 81 Block: &proto.Schema_Block{ 82 Attributes: []*proto.Schema_Attribute{ 83 { 84 Name: "attr", 85 Type: []byte(`"string"`), 86 Required: true, 87 }, 88 }, 89 }, 90 }, 91 }, 92 } 93 } 94 95 func TestGRPCProvider_GetSchema(t *testing.T) { 96 p := &GRPCProvider{ 97 client: mockProviderClient(t), 98 } 99 100 resp := p.GetProviderSchema() 101 checkDiags(t, resp.Diagnostics) 102 } 103 104 // Ensure that gRPC errors are returned early. 105 // Reference: https://github.com/hashicorp/terraform/issues/31047 106 func TestGRPCProvider_GetSchema_GRPCError(t *testing.T) { 107 ctrl := gomock.NewController(t) 108 client := mockproto.NewMockProviderClient(ctrl) 109 110 client.EXPECT().GetSchema( 111 gomock.Any(), 112 gomock.Any(), 113 gomock.Any(), 114 ).Return(&proto.GetProviderSchema_Response{}, fmt.Errorf("test error")) 115 116 p := &GRPCProvider{ 117 client: client, 118 } 119 120 resp := p.GetProviderSchema() 121 122 checkDiagsHasError(t, resp.Diagnostics) 123 } 124 125 // Ensure that provider error diagnostics are returned early. 126 // Reference: https://github.com/hashicorp/terraform/issues/31047 127 func TestGRPCProvider_GetSchema_ResponseErrorDiagnostic(t *testing.T) { 128 ctrl := gomock.NewController(t) 129 client := mockproto.NewMockProviderClient(ctrl) 130 131 client.EXPECT().GetSchema( 132 gomock.Any(), 133 gomock.Any(), 134 gomock.Any(), 135 ).Return(&proto.GetProviderSchema_Response{ 136 Diagnostics: []*proto.Diagnostic{ 137 { 138 Severity: proto.Diagnostic_ERROR, 139 Summary: "error summary", 140 Detail: "error detail", 141 }, 142 }, 143 // Trigger potential panics 144 Provider: &proto.Schema{}, 145 }, nil) 146 147 p := &GRPCProvider{ 148 client: client, 149 } 150 151 resp := p.GetProviderSchema() 152 153 checkDiagsHasError(t, resp.Diagnostics) 154 } 155 156 func TestGRPCProvider_PrepareProviderConfig(t *testing.T) { 157 client := mockProviderClient(t) 158 p := &GRPCProvider{ 159 client: client, 160 } 161 162 client.EXPECT().PrepareProviderConfig( 163 gomock.Any(), 164 gomock.Any(), 165 ).Return(&proto.PrepareProviderConfig_Response{}, nil) 166 167 cfg := hcl2shim.HCL2ValueFromConfigValue(map[string]interface{}{"attr": "value"}) 168 resp := p.ValidateProviderConfig(providers.ValidateProviderConfigRequest{Config: cfg}) 169 checkDiags(t, resp.Diagnostics) 170 } 171 172 func TestGRPCProvider_ValidateResourceConfig(t *testing.T) { 173 client := mockProviderClient(t) 174 p := &GRPCProvider{ 175 client: client, 176 } 177 178 client.EXPECT().ValidateResourceTypeConfig( 179 gomock.Any(), 180 gomock.Any(), 181 ).Return(&proto.ValidateResourceTypeConfig_Response{}, nil) 182 183 cfg := hcl2shim.HCL2ValueFromConfigValue(map[string]interface{}{"attr": "value"}) 184 resp := p.ValidateResourceConfig(providers.ValidateResourceConfigRequest{ 185 TypeName: "resource", 186 Config: cfg, 187 }) 188 checkDiags(t, resp.Diagnostics) 189 } 190 191 func TestGRPCProvider_ValidateDataSourceConfig(t *testing.T) { 192 client := mockProviderClient(t) 193 p := &GRPCProvider{ 194 client: client, 195 } 196 197 client.EXPECT().ValidateDataSourceConfig( 198 gomock.Any(), 199 gomock.Any(), 200 ).Return(&proto.ValidateDataSourceConfig_Response{}, nil) 201 202 cfg := hcl2shim.HCL2ValueFromConfigValue(map[string]interface{}{"attr": "value"}) 203 resp := p.ValidateDataResourceConfig(providers.ValidateDataResourceConfigRequest{ 204 TypeName: "data", 205 Config: cfg, 206 }) 207 checkDiags(t, resp.Diagnostics) 208 } 209 210 func TestGRPCProvider_UpgradeResourceState(t *testing.T) { 211 client := mockProviderClient(t) 212 p := &GRPCProvider{ 213 client: client, 214 } 215 216 client.EXPECT().UpgradeResourceState( 217 gomock.Any(), 218 gomock.Any(), 219 ).Return(&proto.UpgradeResourceState_Response{ 220 UpgradedState: &proto.DynamicValue{ 221 Msgpack: []byte("\x81\xa4attr\xa3bar"), 222 }, 223 }, nil) 224 225 resp := p.UpgradeResourceState(providers.UpgradeResourceStateRequest{ 226 TypeName: "resource", 227 Version: 0, 228 RawStateJSON: []byte(`{"old_attr":"bar"}`), 229 }) 230 checkDiags(t, resp.Diagnostics) 231 232 expected := cty.ObjectVal(map[string]cty.Value{ 233 "attr": cty.StringVal("bar"), 234 }) 235 236 if !cmp.Equal(expected, resp.UpgradedState, typeComparer, valueComparer, equateEmpty) { 237 t.Fatal(cmp.Diff(expected, resp.UpgradedState, typeComparer, valueComparer, equateEmpty)) 238 } 239 } 240 241 func TestGRPCProvider_UpgradeResourceStateJSON(t *testing.T) { 242 client := mockProviderClient(t) 243 p := &GRPCProvider{ 244 client: client, 245 } 246 247 client.EXPECT().UpgradeResourceState( 248 gomock.Any(), 249 gomock.Any(), 250 ).Return(&proto.UpgradeResourceState_Response{ 251 UpgradedState: &proto.DynamicValue{ 252 Json: []byte(`{"attr":"bar"}`), 253 }, 254 }, nil) 255 256 resp := p.UpgradeResourceState(providers.UpgradeResourceStateRequest{ 257 TypeName: "resource", 258 Version: 0, 259 RawStateJSON: []byte(`{"old_attr":"bar"}`), 260 }) 261 checkDiags(t, resp.Diagnostics) 262 263 expected := cty.ObjectVal(map[string]cty.Value{ 264 "attr": cty.StringVal("bar"), 265 }) 266 267 if !cmp.Equal(expected, resp.UpgradedState, typeComparer, valueComparer, equateEmpty) { 268 t.Fatal(cmp.Diff(expected, resp.UpgradedState, typeComparer, valueComparer, equateEmpty)) 269 } 270 } 271 272 func TestGRPCProvider_Configure(t *testing.T) { 273 client := mockProviderClient(t) 274 p := &GRPCProvider{ 275 client: client, 276 } 277 278 client.EXPECT().Configure( 279 gomock.Any(), 280 gomock.Any(), 281 ).Return(&proto.Configure_Response{}, nil) 282 283 resp := p.ConfigureProvider(providers.ConfigureProviderRequest{ 284 Config: cty.ObjectVal(map[string]cty.Value{ 285 "attr": cty.StringVal("foo"), 286 }), 287 }) 288 checkDiags(t, resp.Diagnostics) 289 } 290 291 func TestGRPCProvider_Stop(t *testing.T) { 292 ctrl := gomock.NewController(t) 293 client := mockproto.NewMockProviderClient(ctrl) 294 p := &GRPCProvider{ 295 client: client, 296 } 297 298 client.EXPECT().Stop( 299 gomock.Any(), 300 gomock.Any(), 301 ).Return(&proto.Stop_Response{}, nil) 302 303 err := p.Stop() 304 if err != nil { 305 t.Fatal(err) 306 } 307 } 308 309 func TestGRPCProvider_ReadResource(t *testing.T) { 310 client := mockProviderClient(t) 311 p := &GRPCProvider{ 312 client: client, 313 } 314 315 client.EXPECT().ReadResource( 316 gomock.Any(), 317 gomock.Any(), 318 ).Return(&proto.ReadResource_Response{ 319 NewState: &proto.DynamicValue{ 320 Msgpack: []byte("\x81\xa4attr\xa3bar"), 321 }, 322 }, nil) 323 324 resp := p.ReadResource(providers.ReadResourceRequest{ 325 TypeName: "resource", 326 PriorState: cty.ObjectVal(map[string]cty.Value{ 327 "attr": cty.StringVal("foo"), 328 }), 329 }) 330 331 checkDiags(t, resp.Diagnostics) 332 333 expected := cty.ObjectVal(map[string]cty.Value{ 334 "attr": cty.StringVal("bar"), 335 }) 336 337 if !cmp.Equal(expected, resp.NewState, typeComparer, valueComparer, equateEmpty) { 338 t.Fatal(cmp.Diff(expected, resp.NewState, typeComparer, valueComparer, equateEmpty)) 339 } 340 } 341 342 func TestGRPCProvider_ReadResourceJSON(t *testing.T) { 343 client := mockProviderClient(t) 344 p := &GRPCProvider{ 345 client: client, 346 } 347 348 client.EXPECT().ReadResource( 349 gomock.Any(), 350 gomock.Any(), 351 ).Return(&proto.ReadResource_Response{ 352 NewState: &proto.DynamicValue{ 353 Json: []byte(`{"attr":"bar"}`), 354 }, 355 }, nil) 356 357 resp := p.ReadResource(providers.ReadResourceRequest{ 358 TypeName: "resource", 359 PriorState: cty.ObjectVal(map[string]cty.Value{ 360 "attr": cty.StringVal("foo"), 361 }), 362 }) 363 364 checkDiags(t, resp.Diagnostics) 365 366 expected := cty.ObjectVal(map[string]cty.Value{ 367 "attr": cty.StringVal("bar"), 368 }) 369 370 if !cmp.Equal(expected, resp.NewState, typeComparer, valueComparer, equateEmpty) { 371 t.Fatal(cmp.Diff(expected, resp.NewState, typeComparer, valueComparer, equateEmpty)) 372 } 373 } 374 375 func TestGRPCProvider_ReadEmptyJSON(t *testing.T) { 376 client := mockProviderClient(t) 377 p := &GRPCProvider{ 378 client: client, 379 } 380 381 client.EXPECT().ReadResource( 382 gomock.Any(), 383 gomock.Any(), 384 ).Return(&proto.ReadResource_Response{ 385 NewState: &proto.DynamicValue{ 386 Json: []byte(``), 387 }, 388 }, nil) 389 390 obj := cty.ObjectVal(map[string]cty.Value{ 391 "attr": cty.StringVal("foo"), 392 }) 393 resp := p.ReadResource(providers.ReadResourceRequest{ 394 TypeName: "resource", 395 PriorState: obj, 396 }) 397 398 checkDiags(t, resp.Diagnostics) 399 400 expected := cty.NullVal(obj.Type()) 401 402 if !cmp.Equal(expected, resp.NewState, typeComparer, valueComparer, equateEmpty) { 403 t.Fatal(cmp.Diff(expected, resp.NewState, typeComparer, valueComparer, equateEmpty)) 404 } 405 } 406 407 func TestGRPCProvider_PlanResourceChange(t *testing.T) { 408 client := mockProviderClient(t) 409 p := &GRPCProvider{ 410 client: client, 411 } 412 413 expectedPrivate := []byte(`{"meta": "data"}`) 414 415 client.EXPECT().PlanResourceChange( 416 gomock.Any(), 417 gomock.Any(), 418 ).Return(&proto.PlanResourceChange_Response{ 419 PlannedState: &proto.DynamicValue{ 420 Msgpack: []byte("\x81\xa4attr\xa3bar"), 421 }, 422 RequiresReplace: []*proto.AttributePath{ 423 { 424 Steps: []*proto.AttributePath_Step{ 425 { 426 Selector: &proto.AttributePath_Step_AttributeName{ 427 AttributeName: "attr", 428 }, 429 }, 430 }, 431 }, 432 }, 433 PlannedPrivate: expectedPrivate, 434 }, nil) 435 436 resp := p.PlanResourceChange(providers.PlanResourceChangeRequest{ 437 TypeName: "resource", 438 PriorState: cty.ObjectVal(map[string]cty.Value{ 439 "attr": cty.StringVal("foo"), 440 }), 441 ProposedNewState: cty.ObjectVal(map[string]cty.Value{ 442 "attr": cty.StringVal("bar"), 443 }), 444 Config: cty.ObjectVal(map[string]cty.Value{ 445 "attr": cty.StringVal("bar"), 446 }), 447 }) 448 449 checkDiags(t, resp.Diagnostics) 450 451 expectedState := cty.ObjectVal(map[string]cty.Value{ 452 "attr": cty.StringVal("bar"), 453 }) 454 455 if !cmp.Equal(expectedState, resp.PlannedState, typeComparer, valueComparer, equateEmpty) { 456 t.Fatal(cmp.Diff(expectedState, resp.PlannedState, typeComparer, valueComparer, equateEmpty)) 457 } 458 459 expectedReplace := `[]cty.Path{cty.Path{cty.GetAttrStep{Name:"attr"}}}` 460 replace := fmt.Sprintf("%#v", resp.RequiresReplace) 461 if expectedReplace != replace { 462 t.Fatalf("expected %q, got %q", expectedReplace, replace) 463 } 464 465 if !bytes.Equal(expectedPrivate, resp.PlannedPrivate) { 466 t.Fatalf("expected %q, got %q", expectedPrivate, resp.PlannedPrivate) 467 } 468 } 469 470 func TestGRPCProvider_PlanResourceChangeJSON(t *testing.T) { 471 client := mockProviderClient(t) 472 p := &GRPCProvider{ 473 client: client, 474 } 475 476 expectedPrivate := []byte(`{"meta": "data"}`) 477 478 client.EXPECT().PlanResourceChange( 479 gomock.Any(), 480 gomock.Any(), 481 ).Return(&proto.PlanResourceChange_Response{ 482 PlannedState: &proto.DynamicValue{ 483 Json: []byte(`{"attr":"bar"}`), 484 }, 485 RequiresReplace: []*proto.AttributePath{ 486 { 487 Steps: []*proto.AttributePath_Step{ 488 { 489 Selector: &proto.AttributePath_Step_AttributeName{ 490 AttributeName: "attr", 491 }, 492 }, 493 }, 494 }, 495 }, 496 PlannedPrivate: expectedPrivate, 497 }, nil) 498 499 resp := p.PlanResourceChange(providers.PlanResourceChangeRequest{ 500 TypeName: "resource", 501 PriorState: cty.ObjectVal(map[string]cty.Value{ 502 "attr": cty.StringVal("foo"), 503 }), 504 ProposedNewState: cty.ObjectVal(map[string]cty.Value{ 505 "attr": cty.StringVal("bar"), 506 }), 507 Config: cty.ObjectVal(map[string]cty.Value{ 508 "attr": cty.StringVal("bar"), 509 }), 510 }) 511 512 checkDiags(t, resp.Diagnostics) 513 514 expectedState := cty.ObjectVal(map[string]cty.Value{ 515 "attr": cty.StringVal("bar"), 516 }) 517 518 if !cmp.Equal(expectedState, resp.PlannedState, typeComparer, valueComparer, equateEmpty) { 519 t.Fatal(cmp.Diff(expectedState, resp.PlannedState, typeComparer, valueComparer, equateEmpty)) 520 } 521 522 expectedReplace := `[]cty.Path{cty.Path{cty.GetAttrStep{Name:"attr"}}}` 523 replace := fmt.Sprintf("%#v", resp.RequiresReplace) 524 if expectedReplace != replace { 525 t.Fatalf("expected %q, got %q", expectedReplace, replace) 526 } 527 528 if !bytes.Equal(expectedPrivate, resp.PlannedPrivate) { 529 t.Fatalf("expected %q, got %q", expectedPrivate, resp.PlannedPrivate) 530 } 531 } 532 533 func TestGRPCProvider_ApplyResourceChange(t *testing.T) { 534 client := mockProviderClient(t) 535 p := &GRPCProvider{ 536 client: client, 537 } 538 539 expectedPrivate := []byte(`{"meta": "data"}`) 540 541 client.EXPECT().ApplyResourceChange( 542 gomock.Any(), 543 gomock.Any(), 544 ).Return(&proto.ApplyResourceChange_Response{ 545 NewState: &proto.DynamicValue{ 546 Msgpack: []byte("\x81\xa4attr\xa3bar"), 547 }, 548 Private: expectedPrivate, 549 }, nil) 550 551 resp := p.ApplyResourceChange(providers.ApplyResourceChangeRequest{ 552 TypeName: "resource", 553 PriorState: cty.ObjectVal(map[string]cty.Value{ 554 "attr": cty.StringVal("foo"), 555 }), 556 PlannedState: cty.ObjectVal(map[string]cty.Value{ 557 "attr": cty.StringVal("bar"), 558 }), 559 Config: cty.ObjectVal(map[string]cty.Value{ 560 "attr": cty.StringVal("bar"), 561 }), 562 PlannedPrivate: expectedPrivate, 563 }) 564 565 checkDiags(t, resp.Diagnostics) 566 567 expectedState := cty.ObjectVal(map[string]cty.Value{ 568 "attr": cty.StringVal("bar"), 569 }) 570 571 if !cmp.Equal(expectedState, resp.NewState, typeComparer, valueComparer, equateEmpty) { 572 t.Fatal(cmp.Diff(expectedState, resp.NewState, typeComparer, valueComparer, equateEmpty)) 573 } 574 575 if !bytes.Equal(expectedPrivate, resp.Private) { 576 t.Fatalf("expected %q, got %q", expectedPrivate, resp.Private) 577 } 578 } 579 func TestGRPCProvider_ApplyResourceChangeJSON(t *testing.T) { 580 client := mockProviderClient(t) 581 p := &GRPCProvider{ 582 client: client, 583 } 584 585 expectedPrivate := []byte(`{"meta": "data"}`) 586 587 client.EXPECT().ApplyResourceChange( 588 gomock.Any(), 589 gomock.Any(), 590 ).Return(&proto.ApplyResourceChange_Response{ 591 NewState: &proto.DynamicValue{ 592 Json: []byte(`{"attr":"bar"}`), 593 }, 594 Private: expectedPrivate, 595 }, nil) 596 597 resp := p.ApplyResourceChange(providers.ApplyResourceChangeRequest{ 598 TypeName: "resource", 599 PriorState: cty.ObjectVal(map[string]cty.Value{ 600 "attr": cty.StringVal("foo"), 601 }), 602 PlannedState: cty.ObjectVal(map[string]cty.Value{ 603 "attr": cty.StringVal("bar"), 604 }), 605 Config: cty.ObjectVal(map[string]cty.Value{ 606 "attr": cty.StringVal("bar"), 607 }), 608 PlannedPrivate: expectedPrivate, 609 }) 610 611 checkDiags(t, resp.Diagnostics) 612 613 expectedState := cty.ObjectVal(map[string]cty.Value{ 614 "attr": cty.StringVal("bar"), 615 }) 616 617 if !cmp.Equal(expectedState, resp.NewState, typeComparer, valueComparer, equateEmpty) { 618 t.Fatal(cmp.Diff(expectedState, resp.NewState, typeComparer, valueComparer, equateEmpty)) 619 } 620 621 if !bytes.Equal(expectedPrivate, resp.Private) { 622 t.Fatalf("expected %q, got %q", expectedPrivate, resp.Private) 623 } 624 } 625 626 func TestGRPCProvider_ImportResourceState(t *testing.T) { 627 client := mockProviderClient(t) 628 p := &GRPCProvider{ 629 client: client, 630 } 631 632 expectedPrivate := []byte(`{"meta": "data"}`) 633 634 client.EXPECT().ImportResourceState( 635 gomock.Any(), 636 gomock.Any(), 637 ).Return(&proto.ImportResourceState_Response{ 638 ImportedResources: []*proto.ImportResourceState_ImportedResource{ 639 { 640 TypeName: "resource", 641 State: &proto.DynamicValue{ 642 Msgpack: []byte("\x81\xa4attr\xa3bar"), 643 }, 644 Private: expectedPrivate, 645 }, 646 }, 647 }, nil) 648 649 resp := p.ImportResourceState(providers.ImportResourceStateRequest{ 650 TypeName: "resource", 651 ID: "foo", 652 }) 653 654 checkDiags(t, resp.Diagnostics) 655 656 expectedResource := providers.ImportedResource{ 657 TypeName: "resource", 658 State: cty.ObjectVal(map[string]cty.Value{ 659 "attr": cty.StringVal("bar"), 660 }), 661 Private: expectedPrivate, 662 } 663 664 imported := resp.ImportedResources[0] 665 if !cmp.Equal(expectedResource, imported, typeComparer, valueComparer, equateEmpty) { 666 t.Fatal(cmp.Diff(expectedResource, imported, typeComparer, valueComparer, equateEmpty)) 667 } 668 } 669 func TestGRPCProvider_ImportResourceStateJSON(t *testing.T) { 670 client := mockProviderClient(t) 671 p := &GRPCProvider{ 672 client: client, 673 } 674 675 expectedPrivate := []byte(`{"meta": "data"}`) 676 677 client.EXPECT().ImportResourceState( 678 gomock.Any(), 679 gomock.Any(), 680 ).Return(&proto.ImportResourceState_Response{ 681 ImportedResources: []*proto.ImportResourceState_ImportedResource{ 682 { 683 TypeName: "resource", 684 State: &proto.DynamicValue{ 685 Json: []byte(`{"attr":"bar"}`), 686 }, 687 Private: expectedPrivate, 688 }, 689 }, 690 }, nil) 691 692 resp := p.ImportResourceState(providers.ImportResourceStateRequest{ 693 TypeName: "resource", 694 ID: "foo", 695 }) 696 697 checkDiags(t, resp.Diagnostics) 698 699 expectedResource := providers.ImportedResource{ 700 TypeName: "resource", 701 State: cty.ObjectVal(map[string]cty.Value{ 702 "attr": cty.StringVal("bar"), 703 }), 704 Private: expectedPrivate, 705 } 706 707 imported := resp.ImportedResources[0] 708 if !cmp.Equal(expectedResource, imported, typeComparer, valueComparer, equateEmpty) { 709 t.Fatal(cmp.Diff(expectedResource, imported, typeComparer, valueComparer, equateEmpty)) 710 } 711 } 712 713 func TestGRPCProvider_ReadDataSource(t *testing.T) { 714 client := mockProviderClient(t) 715 p := &GRPCProvider{ 716 client: client, 717 } 718 719 client.EXPECT().ReadDataSource( 720 gomock.Any(), 721 gomock.Any(), 722 ).Return(&proto.ReadDataSource_Response{ 723 State: &proto.DynamicValue{ 724 Msgpack: []byte("\x81\xa4attr\xa3bar"), 725 }, 726 }, nil) 727 728 resp := p.ReadDataSource(providers.ReadDataSourceRequest{ 729 TypeName: "data", 730 Config: cty.ObjectVal(map[string]cty.Value{ 731 "attr": cty.StringVal("foo"), 732 }), 733 }) 734 735 checkDiags(t, resp.Diagnostics) 736 737 expected := cty.ObjectVal(map[string]cty.Value{ 738 "attr": cty.StringVal("bar"), 739 }) 740 741 if !cmp.Equal(expected, resp.State, typeComparer, valueComparer, equateEmpty) { 742 t.Fatal(cmp.Diff(expected, resp.State, typeComparer, valueComparer, equateEmpty)) 743 } 744 } 745 746 func TestGRPCProvider_ReadDataSourceJSON(t *testing.T) { 747 client := mockProviderClient(t) 748 p := &GRPCProvider{ 749 client: client, 750 } 751 752 client.EXPECT().ReadDataSource( 753 gomock.Any(), 754 gomock.Any(), 755 ).Return(&proto.ReadDataSource_Response{ 756 State: &proto.DynamicValue{ 757 Json: []byte(`{"attr":"bar"}`), 758 }, 759 }, nil) 760 761 resp := p.ReadDataSource(providers.ReadDataSourceRequest{ 762 TypeName: "data", 763 Config: cty.ObjectVal(map[string]cty.Value{ 764 "attr": cty.StringVal("foo"), 765 }), 766 }) 767 768 checkDiags(t, resp.Diagnostics) 769 770 expected := cty.ObjectVal(map[string]cty.Value{ 771 "attr": cty.StringVal("bar"), 772 }) 773 774 if !cmp.Equal(expected, resp.State, typeComparer, valueComparer, equateEmpty) { 775 t.Fatal(cmp.Diff(expected, resp.State, typeComparer, valueComparer, equateEmpty)) 776 } 777 }