diff --git a/internal/states/resource_test.go b/internal/states/resource_test.go index 53447e3d40f0..221e41abb0ae 100644 --- a/internal/states/resource_test.go +++ b/internal/states/resource_test.go @@ -8,6 +8,15 @@ import ( ) func TestResourceInstanceDeposeCurrentObject(t *testing.T) { + t.Run("nil resource", func(t *testing.T) { + var nilRI *ResourceInstance + dk := nilRI.deposeCurrentObject(NotDeposed) + t.Logf("deposedKey (nil receiver) is %q", dk) + + if dk != NotDeposed { + t.Fatalf("expected NotDeposed for nil receiver, got %q", dk) + } + }) obj := &ResourceInstanceObjectSrc{ // Empty for the sake of this test, because we're just going to // compare by pointer below anyway. diff --git a/internal/states/state_test.go b/internal/states/state_test.go index 5dc36e4b0b01..0ce3f74c806d 100644 --- a/internal/states/state_test.go +++ b/internal/states/state_test.go @@ -7,6 +7,7 @@ import ( "fmt" "reflect" "testing" + "time" "github.com/go-test/deep" "github.com/google/go-cmp/cmp" @@ -337,6 +338,18 @@ func TestStateHasResourceInstanceObjects(t *testing.T) { s := ss.Lock() delete(s.Modules[""].Resources["test.foo"].Instances, addrs.NoKey) ss.Unlock() + done := make(chan struct{}) + go func() { + ss.Lock() + ss.Unlock() + close(done) + }() + select { + case <-done: + // OK: lock was released + case <-time.After(500 * time.Millisecond): + t.Fatalf("Unlock did not release SyncState lock (timed out acquiring lock again)") + } }, false, }, @@ -1009,6 +1022,70 @@ func TestState_MoveModule(t *testing.T) { }) } +func TestState_ProviderAddrs(t *testing.T) { + // 1) nil state + var nilState *State + if got := nilState.ProviderAddrs(); got != nil { + t.Fatalf("nil state: expected nil, got %#v", got) + } + + // 2) empty state + empty := NewState() + if got := empty.ProviderAddrs(); got != nil { + t.Fatalf("empty state: expected nil, got %#v", got) + } + + // 3) populated state + s := NewState() + + rootAWS := addrs.AbsProviderConfig{ + Module: addrs.RootModule, + Provider: addrs.NewDefaultProvider("aws"), + } + rootGoogle := addrs.AbsProviderConfig{ + Module: addrs.RootModule, + Provider: addrs.NewDefaultProvider("google"), + } + childAWS := addrs.AbsProviderConfig{ + Module: addrs.RootModule.Child("child"), + Provider: addrs.NewDefaultProvider("aws"), + } + + rm := s.RootModule() + rm.SetResourceInstanceCurrent( + addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_thing", Name: "foo"}.Instance(addrs.NoKey), + &ResourceInstanceObjectSrc{Status: ObjectReady, SchemaVersion: 1, AttrsJSON: []byte(`{}`)}, + rootAWS, + ) + + rm.SetResourceInstanceCurrent( + addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_thing", Name: "bar"}.Instance(addrs.NoKey), + &ResourceInstanceObjectSrc{Status: ObjectReady, SchemaVersion: 1, AttrsJSON: []byte(`{}`)}, + rootAWS, + ) + + rm.SetResourceInstanceCurrent( + addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_thing", Name: "baz"}.Instance(addrs.NoKey), + &ResourceInstanceObjectSrc{Status: ObjectReady, SchemaVersion: 1, AttrsJSON: []byte(`{}`)}, + rootGoogle, + ) + + childMI := addrs.RootModuleInstance.Child("child", addrs.NoKey) + cm := s.EnsureModule(childMI) + cm.SetResourceInstanceCurrent( + addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_thing", Name: "child"}.Instance(addrs.NoKey), + &ResourceInstanceObjectSrc{Status: ObjectReady, SchemaVersion: 1, AttrsJSON: []byte(`{}`)}, + childAWS, + ) + + got := s.ProviderAddrs() + expected := []addrs.AbsProviderConfig{childAWS, rootAWS, rootGoogle} + + if !reflect.DeepEqual(got, expected) { + t.Fatalf("unexpected provider addrs\nexpected: %#v\ngot: %#v", expected, got) + } +} + func mustParseModuleInstanceStr(str string) addrs.ModuleInstance { addr, diags := addrs.ParseModuleInstanceStr(str) if diags.HasErrors() {