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