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