github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/state/remote/testing.go (about) 1 package remote 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/hashicorp/terraform/state" 8 "github.com/hashicorp/terraform/states/statefile" 9 ) 10 11 // TestClient is a generic function to test any client. 12 func TestClient(t *testing.T, c Client) { 13 var buf bytes.Buffer 14 s := state.TestStateInitial() 15 sf := statefile.New(s, "stub-lineage", 2) 16 err := statefile.Write(sf, &buf) 17 if err != nil { 18 t.Fatalf("err: %s", err) 19 } 20 data := buf.Bytes() 21 22 if err := c.Put(data); err != nil { 23 t.Fatalf("put: %s", err) 24 } 25 26 p, err := c.Get() 27 if err != nil { 28 t.Fatalf("get: %s", err) 29 } 30 if !bytes.Equal(p.Data, data) { 31 t.Fatalf("expected full state %q\n\ngot: %q", string(p.Data), string(data)) 32 } 33 34 if err := c.Delete(); err != nil { 35 t.Fatalf("delete: %s", err) 36 } 37 38 p, err = c.Get() 39 if err != nil { 40 t.Fatalf("get: %s", err) 41 } 42 if p != nil { 43 t.Fatalf("expected empty state, got: %q", string(p.Data)) 44 } 45 } 46 47 // Test the lock implementation for a remote.Client. 48 // This test requires 2 client instances, in oder to have multiple remote 49 // clients since some implementations may tie the client to the lock, or may 50 // have reentrant locks. 51 func TestRemoteLocks(t *testing.T, a, b Client) { 52 lockerA, ok := a.(state.Locker) 53 if !ok { 54 t.Fatal("client A not a state.Locker") 55 } 56 57 lockerB, ok := b.(state.Locker) 58 if !ok { 59 t.Fatal("client B not a state.Locker") 60 } 61 62 infoA := state.NewLockInfo() 63 infoA.Operation = "test" 64 infoA.Who = "clientA" 65 66 infoB := state.NewLockInfo() 67 infoB.Operation = "test" 68 infoB.Who = "clientB" 69 70 lockIDA, err := lockerA.Lock(infoA) 71 if err != nil { 72 t.Fatal("unable to get initial lock:", err) 73 } 74 75 _, err = lockerB.Lock(infoB) 76 if err == nil { 77 lockerA.Unlock(lockIDA) 78 t.Fatal("client B obtained lock while held by client A") 79 } 80 81 if err := lockerA.Unlock(lockIDA); err != nil { 82 t.Fatal("error unlocking client A", err) 83 } 84 85 lockIDB, err := lockerB.Lock(infoB) 86 if err != nil { 87 t.Fatal("unable to obtain lock from client B") 88 } 89 90 if lockIDB == lockIDA { 91 t.Fatalf("duplicate lock IDs: %q", lockIDB) 92 } 93 94 if err = lockerB.Unlock(lockIDB); err != nil { 95 t.Fatal("error unlocking client B:", err) 96 } 97 98 // TODO: Should we enforce that Unlock requires the correct ID? 99 }